1 /* 2 * Memory-mapped interface driver for DW SPI Core 3 * 4 * Copyright (c) 2010, Octasic semiconductor. 5 * 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. 9 */ 10 11 #include <linux/clk.h> 12 #include <linux/err.h> 13 #include <linux/interrupt.h> 14 #include <linux/platform_device.h> 15 #include <linux/slab.h> 16 #include <linux/spi/spi.h> 17 #include <linux/scatterlist.h> 18 #include <linux/module.h> 19 20 #include "spi-dw.h" 21 22 #define DRIVER_NAME "dw_spi_mmio" 23 24 struct dw_spi_mmio { 25 struct dw_spi dws; 26 struct clk *clk; 27 }; 28 29 static int dw_spi_mmio_probe(struct platform_device *pdev) 30 { 31 struct dw_spi_mmio *dwsmmio; 32 struct dw_spi *dws; 33 struct resource *mem; 34 int ret; 35 36 dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mmio), 37 GFP_KERNEL); 38 if (!dwsmmio) 39 return -ENOMEM; 40 41 dws = &dwsmmio->dws; 42 43 /* Get basic io resource and map it */ 44 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 45 if (!mem) { 46 dev_err(&pdev->dev, "no mem resource?\n"); 47 return -EINVAL; 48 } 49 50 dws->regs = devm_ioremap_resource(&pdev->dev, mem); 51 if (IS_ERR(dws->regs)) { 52 dev_err(&pdev->dev, "SPI region map failed\n"); 53 return PTR_ERR(dws->regs); 54 } 55 56 dws->irq = platform_get_irq(pdev, 0); 57 if (dws->irq < 0) { 58 dev_err(&pdev->dev, "no irq resource?\n"); 59 return dws->irq; /* -ENXIO */ 60 } 61 62 dwsmmio->clk = devm_clk_get(&pdev->dev, NULL); 63 if (IS_ERR(dwsmmio->clk)) 64 return PTR_ERR(dwsmmio->clk); 65 ret = clk_prepare_enable(dwsmmio->clk); 66 if (ret) 67 return ret; 68 69 dws->bus_num = 0; 70 dws->num_cs = 4; 71 dws->max_freq = clk_get_rate(dwsmmio->clk); 72 73 ret = dw_spi_add_host(&pdev->dev, dws); 74 if (ret) 75 goto out; 76 77 platform_set_drvdata(pdev, dwsmmio); 78 return 0; 79 80 out: 81 clk_disable_unprepare(dwsmmio->clk); 82 return ret; 83 } 84 85 static int dw_spi_mmio_remove(struct platform_device *pdev) 86 { 87 struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev); 88 89 clk_disable_unprepare(dwsmmio->clk); 90 dw_spi_remove_host(&dwsmmio->dws); 91 92 return 0; 93 } 94 95 static struct platform_driver dw_spi_mmio_driver = { 96 .probe = dw_spi_mmio_probe, 97 .remove = dw_spi_mmio_remove, 98 .driver = { 99 .name = DRIVER_NAME, 100 .owner = THIS_MODULE, 101 }, 102 }; 103 module_platform_driver(dw_spi_mmio_driver); 104 105 MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>"); 106 MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core"); 107 MODULE_LICENSE("GPL v2"); 108