2 * rockchip spi interface driver for DW SPI Core
4 * Copyright (c) 2014, ROCKCHIP Corporation.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 #include <linux/interrupt.h>
21 #include <linux/slab.h>
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/workqueue.h>
25 #include <linux/interrupt.h>
26 #include <linux/delay.h>
27 #include <linux/clk.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/dmaengine.h>
30 #include <linux/platform_device.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/spi/spi.h>
33 #include <linux/gpio.h>
35 #include <linux/of_gpio.h>
36 #include <linux/platform_data/spi-rockchip.h>
38 #include "spi-rockchip-core.h"
41 #define DRIVER_NAME "rockchip_spi_driver_data"
42 #define SPI_MAX_FREQUENCY 24000000
44 struct rockchip_spi_driver_data {
45 struct platform_device *pdev;
47 struct rockchip_spi_info *info;
53 static struct rockchip_spi_info *rockchip_spi_parse_dt(struct device *dev)
55 struct rockchip_spi_info *info;
58 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
60 dev_err(dev, "memory allocation for spi_info failed\n");
61 return ERR_PTR(-ENOMEM);
64 if (of_property_read_u32(dev->of_node, "rockchip,spi-src-clk", &temp)) {
65 dev_warn(dev, "spi bus clock parent not specified, using clock at index 0 as parent\n");
68 info->src_clk_nr = temp;
71 if (of_property_read_u32(dev->of_node, "bus-num", &temp)) {
72 dev_warn(dev, "number of bus not specified, assuming bus 0\n");
78 if (of_property_read_u32(dev->of_node, "num-cs", &temp)) {
79 dev_warn(dev, "number of chip select lines not specified, assuming 1 chip select line\n");
85 if (of_property_read_u32(dev->of_node, "max-freq", &temp)) {
86 dev_warn(dev, "fail to get max-freq,default set %dHZ\n",SPI_MAX_FREQUENCY);
87 info->spi_freq = SPI_MAX_FREQUENCY;
89 info->spi_freq = temp;
92 //printk("%s:line=%d,src_clk_nr=%d,bus_num=%d,num_cs=%d\n",__func__, __LINE__,info->src_clk_nr,info->bus_num,info->num_cs);
97 static struct rockchip_spi_info *rockchip_spi_parse_dt(struct device *dev)
99 return dev->platform_data;
104 static int rockchip_spi_probe(struct platform_device *pdev)
106 struct resource *mem_res;
107 struct rockchip_spi_driver_data *sdd;
108 struct rockchip_spi_info *info = pdev->dev.platform_data;
113 if (!info && pdev->dev.of_node) {
114 info = rockchip_spi_parse_dt(&pdev->dev);
116 return PTR_ERR(info);
120 dev_err(&pdev->dev, "platform_data missing!\n");
124 sdd = kzalloc(sizeof(struct rockchip_spi_driver_data), GFP_KERNEL);
135 atomic_set(&dws->debug_flag, 0);//debug flag
137 /* Get basic io resource and map it */
138 irq = platform_get_irq(pdev, 0);
140 dev_warn(&pdev->dev, "Failed to get IRQ: %d\n", irq);
144 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
145 if (mem_res == NULL) {
146 dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
151 dws->regs = ioremap(mem_res->start, (mem_res->end - mem_res->start) + 1);
157 dws->paddr = mem_res->start;
158 dws->iolen = (mem_res->end - mem_res->start) + 1;
160 printk(KERN_INFO "dws->regs: %p\n", dws->regs);
163 if (pdev->dev.of_node) {
164 ret = of_alias_get_id(pdev->dev.of_node, "spi");
166 dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
168 goto err_release_mem;
172 info->bus_num = pdev->id;
176 sdd->clk_spi = devm_clk_get(&pdev->dev, "spi");
177 if (IS_ERR(sdd->clk_spi)) {
178 dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
179 ret = PTR_ERR(sdd->clk_spi);
183 if (clk_prepare_enable(sdd->clk_spi)) {
184 dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
189 sprintf(clk_name, "pclk_spi%d", info->src_clk_nr);
190 sdd->pclk_spi = devm_clk_get(&pdev->dev, clk_name);
191 if (IS_ERR(sdd->pclk_spi)) {
193 "Unable to acquire clock '%s'\n", clk_name);
194 ret = PTR_ERR(sdd->pclk_spi);
198 if (clk_prepare_enable(sdd->pclk_spi)) {
199 dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
204 clk_set_rate(sdd->clk_spi, info->spi_freq);
206 dws->max_freq = clk_get_rate(sdd->clk_spi);
207 dws->parent_dev = &pdev->dev;
208 dws->bus_num = info->bus_num;
209 dws->num_cs = info->num_cs;
211 dws->clk_spi = sdd->clk_spi;
212 dws->pclk_spi = sdd->pclk_spi;
215 * handling for rockchip paltforms, like dma setup,
216 * clock rate, FIFO depth.
219 #ifdef CONFIG_SPI_ROCKCHIP_DMA
220 ret = dw_spi_dma_init(dws);
222 printk("%s:fail to init dma\n",__func__);
225 ret = dw_spi_add_host(dws);
227 goto err_release_mem;
229 platform_set_drvdata(pdev, sdd);
231 printk("%s:num_cs=%d,bus_num=%d,irq=%d,freq=%d ok\n",__func__, info->num_cs, info->bus_num, irq, dws->max_freq);
235 release_mem_region(mem_res->start, (mem_res->end - mem_res->start) + 1);
237 clk_disable_unprepare(sdd->pclk_spi);
239 clk_disable_unprepare(sdd->clk_spi);
247 static int rockchip_spi_remove(struct platform_device *pdev)
249 struct rockchip_spi_driver_data *sdd = platform_get_drvdata(pdev);
251 platform_set_drvdata(pdev, NULL);
252 dw_spi_remove_host(&sdd->dws);
253 iounmap(sdd->dws.regs);
259 #ifdef CONFIG_PM_SLEEP
260 static int rockchip_spi_suspend(struct device *dev)
262 struct rockchip_spi_driver_data *sdd = dev_get_drvdata(dev);
265 ret = dw_spi_suspend_host(&sdd->dws);
270 static int rockchip_spi_resume(struct device *dev)
272 struct rockchip_spi_driver_data *sdd = dev_get_drvdata(dev);
275 ret = dw_spi_resume_host(&sdd->dws);
279 #endif /* CONFIG_PM_SLEEP */
281 #ifdef CONFIG_PM_RUNTIME
282 static int rockchip_spi_runtime_suspend(struct device *dev)
284 struct rockchip_spi_driver_data *sdd = dev_get_drvdata(dev);
285 struct dw_spi *dws = &sdd->dws;
287 clk_disable_unprepare(sdd->clk_spi);
288 clk_disable_unprepare(sdd->pclk_spi);
291 DBG_SPI("%s\n",__func__);
296 static int rockchip_spi_runtime_resume(struct device *dev)
298 struct rockchip_spi_driver_data *sdd = dev_get_drvdata(dev);
299 struct dw_spi *dws = &sdd->dws;
301 clk_prepare_enable(sdd->pclk_spi);
302 clk_prepare_enable(sdd->clk_spi);
304 DBG_SPI("%s\n",__func__);
307 #endif /* CONFIG_PM_RUNTIME */
309 static const struct dev_pm_ops rockchip_spi_pm = {
310 SET_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)
311 SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend,
312 rockchip_spi_runtime_resume, NULL)
316 static const struct of_device_id rockchip_spi_dt_match[] = {
317 { .compatible = "rockchip,rockchip-spi",
321 MODULE_DEVICE_TABLE(of, rockchip_spi_dt_match);
322 #endif /* CONFIG_OF */
324 static struct platform_driver rockchip_spi_driver = {
326 .name = "rockchip-spi",
327 .owner = THIS_MODULE,
328 .pm = &rockchip_spi_pm,
329 .of_match_table = of_match_ptr(rockchip_spi_dt_match),
331 .remove = rockchip_spi_remove,
333 MODULE_ALIAS("platform:rockchip-spi");
335 static int __init rockchip_spi_init(void)
337 return platform_driver_probe(&rockchip_spi_driver, rockchip_spi_probe);
339 module_init(rockchip_spi_init);
341 static void __exit rockchip_spi_exit(void)
343 platform_driver_unregister(&rockchip_spi_driver);
345 module_exit(rockchip_spi_exit);
347 MODULE_AUTHOR("Luo Wei <lw@rock-chips.com>");
348 MODULE_DESCRIPTION("ROCKCHIP SPI Controller Driver");
349 MODULE_LICENSE("GPL");