atmel-ssc.c (31974361761b18e07e821d3b262e34f1a2d105cb) | atmel-ssc.c (2d6bed9ca93e98685bc5038d686984fd449cd978) |
---|---|
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. --- 4 unchanged lines hidden (view full) --- 13#include <linux/clk.h> 14#include <linux/err.h> 15#include <linux/io.h> 16#include <linux/spinlock.h> 17#include <linux/atmel-ssc.h> 18#include <linux/slab.h> 19#include <linux/module.h> 20 | 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. --- 4 unchanged lines hidden (view full) --- 13#include <linux/clk.h> 14#include <linux/err.h> 15#include <linux/io.h> 16#include <linux/spinlock.h> 17#include <linux/atmel-ssc.h> 18#include <linux/slab.h> 19#include <linux/module.h> 20 |
21#include <linux/of.h> 22 | |
23/* Serialize access to ssc_list and user count */ 24static DEFINE_SPINLOCK(user_lock); 25static LIST_HEAD(ssc_list); 26 27struct ssc_device *ssc_request(unsigned int ssc_num) 28{ 29 int ssc_valid = 0; 30 struct ssc_device *ssc; 31 32 spin_lock(&user_lock); 33 list_for_each_entry(ssc, &ssc_list, list) { | 21/* Serialize access to ssc_list and user count */ 22static DEFINE_SPINLOCK(user_lock); 23static LIST_HEAD(ssc_list); 24 25struct ssc_device *ssc_request(unsigned int ssc_num) 26{ 27 int ssc_valid = 0; 28 struct ssc_device *ssc; 29 30 spin_lock(&user_lock); 31 list_for_each_entry(ssc, &ssc_list, list) { |
34 if (ssc->pdev->dev.of_node) { 35 if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc") 36 == ssc_num) { 37 ssc_valid = 1; 38 break; 39 } 40 } else if (ssc->pdev->id == ssc_num) { | 32 if (ssc->pdev->id == ssc_num) { |
41 ssc_valid = 1; 42 break; 43 } 44 } 45 46 if (!ssc_valid) { 47 spin_unlock(&user_lock); 48 pr_err("ssc: ssc%d platform device is missing\n", ssc_num); --- 22 unchanged lines hidden (view full) --- 71 clk_disable(ssc->clk); 72 } else { 73 dev_dbg(&ssc->pdev->dev, "device already free\n"); 74 } 75 spin_unlock(&user_lock); 76} 77EXPORT_SYMBOL(ssc_free); 78 | 33 ssc_valid = 1; 34 break; 35 } 36 } 37 38 if (!ssc_valid) { 39 spin_unlock(&user_lock); 40 pr_err("ssc: ssc%d platform device is missing\n", ssc_num); --- 22 unchanged lines hidden (view full) --- 63 clk_disable(ssc->clk); 64 } else { 65 dev_dbg(&ssc->pdev->dev, "device already free\n"); 66 } 67 spin_unlock(&user_lock); 68} 69EXPORT_SYMBOL(ssc_free); 70 |
79static struct atmel_ssc_platform_data at91rm9200_config = { 80 .use_dma = 0, 81}; 82 83static struct atmel_ssc_platform_data at91sam9g45_config = { 84 .use_dma = 1, 85}; 86 87static const struct platform_device_id atmel_ssc_devtypes[] = { 88 { 89 .name = "at91rm9200_ssc", 90 .driver_data = (unsigned long) &at91rm9200_config, 91 }, { 92 .name = "at91sam9g45_ssc", 93 .driver_data = (unsigned long) &at91sam9g45_config, 94 }, { 95 /* sentinel */ 96 } 97}; 98 99#ifdef CONFIG_OF 100static const struct of_device_id atmel_ssc_dt_ids[] = { 101 { 102 .compatible = "atmel,at91rm9200-ssc", 103 .data = &at91rm9200_config, 104 }, { 105 .compatible = "atmel,at91sam9g45-ssc", 106 .data = &at91sam9g45_config, 107 }, { 108 /* sentinel */ 109 } 110}; 111MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids); 112#endif 113 114static inline const struct atmel_ssc_platform_data * __init 115 atmel_ssc_get_driver_data(struct platform_device *pdev) | 71static int __init ssc_probe(struct platform_device *pdev) |
116{ | 72{ |
117 if (pdev->dev.of_node) { 118 const struct of_device_id *match; 119 match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node); 120 if (match == NULL) 121 return NULL; 122 return match->data; 123 } 124 125 return (struct atmel_ssc_platform_data *) 126 platform_get_device_id(pdev)->driver_data; 127} 128 129static int ssc_probe(struct platform_device *pdev) 130{ | 73 int retval = 0; |
131 struct resource *regs; 132 struct ssc_device *ssc; | 74 struct resource *regs; 75 struct ssc_device *ssc; |
133 const struct atmel_ssc_platform_data *plat_dat; | |
134 | 76 |
135 ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); | 77 ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL); |
136 if (!ssc) { 137 dev_dbg(&pdev->dev, "out of memory\n"); | 78 if (!ssc) { 79 dev_dbg(&pdev->dev, "out of memory\n"); |
138 return -ENOMEM; | 80 retval = -ENOMEM; 81 goto out; |
139 } 140 | 82 } 83 |
141 ssc->pdev = pdev; 142 143 plat_dat = atmel_ssc_get_driver_data(pdev); 144 if (!plat_dat) 145 return -ENODEV; 146 ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat; 147 | |
148 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 149 if (!regs) { 150 dev_dbg(&pdev->dev, "no mmio resource defined\n"); | 84 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 85 if (!regs) { 86 dev_dbg(&pdev->dev, "no mmio resource defined\n"); |
151 return -ENXIO; | 87 retval = -ENXIO; 88 goto out_free; |
152 } 153 | 89 } 90 |
154 ssc->regs = devm_request_and_ioremap(&pdev->dev, regs); 155 if (!ssc->regs) { 156 dev_dbg(&pdev->dev, "ioremap failed\n"); 157 return -EINVAL; 158 } 159 160 ssc->phybase = regs->start; 161 162 ssc->clk = devm_clk_get(&pdev->dev, "pclk"); | 91 ssc->clk = clk_get(&pdev->dev, "pclk"); |
163 if (IS_ERR(ssc->clk)) { 164 dev_dbg(&pdev->dev, "no pclk clock defined\n"); | 92 if (IS_ERR(ssc->clk)) { 93 dev_dbg(&pdev->dev, "no pclk clock defined\n"); |
165 return -ENXIO; | 94 retval = -ENXIO; 95 goto out_free; |
166 } 167 | 96 } 97 |
98 ssc->pdev = pdev; 99 ssc->regs = ioremap(regs->start, resource_size(regs)); 100 if (!ssc->regs) { 101 dev_dbg(&pdev->dev, "ioremap failed\n"); 102 retval = -EINVAL; 103 goto out_clk; 104 } 105 |
|
168 /* disable all interrupts */ 169 clk_enable(ssc->clk); 170 ssc_writel(ssc->regs, IDR, ~0UL); 171 ssc_readl(ssc->regs, SR); 172 clk_disable(ssc->clk); 173 174 ssc->irq = platform_get_irq(pdev, 0); 175 if (!ssc->irq) { 176 dev_dbg(&pdev->dev, "could not get irq\n"); | 106 /* disable all interrupts */ 107 clk_enable(ssc->clk); 108 ssc_writel(ssc->regs, IDR, ~0UL); 109 ssc_readl(ssc->regs, SR); 110 clk_disable(ssc->clk); 111 112 ssc->irq = platform_get_irq(pdev, 0); 113 if (!ssc->irq) { 114 dev_dbg(&pdev->dev, "could not get irq\n"); |
177 return -ENXIO; | 115 retval = -ENXIO; 116 goto out_unmap; |
178 } 179 180 spin_lock(&user_lock); 181 list_add_tail(&ssc->list, &ssc_list); 182 spin_unlock(&user_lock); 183 184 platform_set_drvdata(pdev, ssc); 185 186 dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", 187 ssc->regs, ssc->irq); 188 | 117 } 118 119 spin_lock(&user_lock); 120 list_add_tail(&ssc->list, &ssc_list); 121 spin_unlock(&user_lock); 122 123 platform_set_drvdata(pdev, ssc); 124 125 dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", 126 ssc->regs, ssc->irq); 127 |
189 return 0; | 128 goto out; 129 130out_unmap: 131 iounmap(ssc->regs); 132out_clk: 133 clk_put(ssc->clk); 134out_free: 135 kfree(ssc); 136out: 137 return retval; |
190} 191 192static int __devexit ssc_remove(struct platform_device *pdev) 193{ 194 struct ssc_device *ssc = platform_get_drvdata(pdev); 195 196 spin_lock(&user_lock); | 138} 139 140static int __devexit ssc_remove(struct platform_device *pdev) 141{ 142 struct ssc_device *ssc = platform_get_drvdata(pdev); 143 144 spin_lock(&user_lock); |
145 iounmap(ssc->regs); 146 clk_put(ssc->clk); |
|
197 list_del(&ssc->list); | 147 list_del(&ssc->list); |
148 kfree(ssc); |
|
198 spin_unlock(&user_lock); 199 200 return 0; 201} 202 203static struct platform_driver ssc_driver = { | 149 spin_unlock(&user_lock); 150 151 return 0; 152} 153 154static struct platform_driver ssc_driver = { |
155 .remove = ssc_remove, |
|
204 .driver = { 205 .name = "ssc", 206 .owner = THIS_MODULE, | 156 .driver = { 157 .name = "ssc", 158 .owner = THIS_MODULE, |
207 .of_match_table = of_match_ptr(atmel_ssc_dt_ids), | |
208 }, | 159 }, |
209 .id_table = atmel_ssc_devtypes, 210 .probe = ssc_probe, 211 .remove = __devexit_p(ssc_remove), | |
212}; | 160}; |
213module_platform_driver(ssc_driver); | |
214 | 161 |
162static int __init ssc_init(void) 163{ 164 return platform_driver_probe(&ssc_driver, ssc_probe); 165} 166module_init(ssc_init); 167 168static void __exit ssc_exit(void) 169{ 170 platform_driver_unregister(&ssc_driver); 171} 172module_exit(ssc_exit); 173 |
|
215MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); 216MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); 217MODULE_LICENSE("GPL"); 218MODULE_ALIAS("platform:ssc"); | 174MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); 175MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); 176MODULE_LICENSE("GPL"); 177MODULE_ALIAS("platform:ssc"); |