1/* 2 * Copyright (c) 2009 Nuvoton technology. 3 * Wan ZongShun <mcuos.com@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 */ 10 11#include <linux/module.h> 12#include <linux/spinlock.h> 13#include <linux/interrupt.h> 14#include <linux/delay.h> 15#include <linux/errno.h> 16#include <linux/err.h> 17#include <linux/clk.h> 18#include <linux/device.h> 19#include <linux/platform_device.h> 20#include <linux/gpio.h> 21#include <linux/io.h> 22#include <linux/slab.h> 23 24#include <linux/spi/spi.h> 25#include <linux/spi/spi_bitbang.h> 26 27#include <linux/platform_data/spi-nuc900.h> 28 29/* usi registers offset */ 30#define USI_CNT 0x00 31#define USI_DIV 0x04 32#define USI_SSR 0x08 33#define USI_RX0 0x10 34#define USI_TX0 0x10 35 36/* usi register bit */ 37#define ENINT (0x01 << 17) 38#define ENFLG (0x01 << 16) 39#define SLEEP (0x0f << 12) 40#define TXNUM (0x03 << 8) 41#define TXBITLEN (0x1f << 3) 42#define TXNEG (0x01 << 2) 43#define RXNEG (0x01 << 1) 44#define LSB (0x01 << 10) 45#define SELECTLEV (0x01 << 2) 46#define SELECTPOL (0x01 << 31) 47#define SELECTSLAVE 0x01 48#define GOBUSY 0x01 49 50struct nuc900_spi { 51 struct spi_bitbang bitbang; 52 struct completion done; 53 void __iomem *regs; 54 int irq; 55 int len; 56 int count; 57 const unsigned char *tx; 58 unsigned char *rx; 59 struct clk *clk; 60 struct spi_master *master; 61 struct nuc900_spi_info *pdata; 62 spinlock_t lock; 63}; 64 65static inline struct nuc900_spi *to_hw(struct spi_device *sdev) 66{ 67 return spi_master_get_devdata(sdev->master); 68} 69 70static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr) 71{ 72 struct nuc900_spi *hw = to_hw(spi); 73 unsigned int val; 74 unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0; 75 unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0; 76 unsigned long flags; 77 78 spin_lock_irqsave(&hw->lock, flags); 79 80 val = __raw_readl(hw->regs + USI_SSR); 81 82 if (!cs) 83 val &= ~SELECTLEV; 84 else 85 val |= SELECTLEV; 86 87 if (!ssr) 88 val &= ~SELECTSLAVE; 89 else 90 val |= SELECTSLAVE; 91 92 __raw_writel(val, hw->regs + USI_SSR); 93 94 val = __raw_readl(hw->regs + USI_CNT); 95 96 if (!cpol) 97 val &= ~SELECTPOL; 98 else 99 val |= SELECTPOL; 100 101 __raw_writel(val, hw->regs + USI_CNT); 102 103 spin_unlock_irqrestore(&hw->lock, flags); 104} 105 106static void nuc900_spi_chipsel(struct spi_device *spi, int value) 107{ 108 switch (value) { 109 case BITBANG_CS_INACTIVE: 110 nuc900_slave_select(spi, 0); 111 break; 112 113 case BITBANG_CS_ACTIVE: 114 nuc900_slave_select(spi, 1); 115 break; 116 } 117} 118 119static void nuc900_spi_setup_txnum(struct nuc900_spi *hw, unsigned int txnum) 120{ 121 unsigned int val; 122 unsigned long flags; 123 124 spin_lock_irqsave(&hw->lock, flags); 125 126 val = __raw_readl(hw->regs + USI_CNT) & ~TXNUM; 127 128 if (txnum) 129 val |= txnum << 0x08; 130 131 __raw_writel(val, hw->regs + USI_CNT); 132 133 spin_unlock_irqrestore(&hw->lock, flags); 134 135} 136 137static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw, 138 unsigned int txbitlen) 139{ 140 unsigned int val; 141 unsigned long flags; 142 143 spin_lock_irqsave(&hw->lock, flags); 144 145 val = __raw_readl(hw->regs + USI_CNT) & ~TXBITLEN; 146 147 val |= (txbitlen << 0x03); 148 149 __raw_writel(val, hw->regs + USI_CNT); 150 151 spin_unlock_irqrestore(&hw->lock, flags); 152} 153 154static void nuc900_spi_gobusy(struct nuc900_spi *hw) 155{ 156 unsigned int val; 157 unsigned long flags; 158 159 spin_lock_irqsave(&hw->lock, flags); 160 161 val = __raw_readl(hw->regs + USI_CNT); 162 163 val |= GOBUSY; 164 165 __raw_writel(val, hw->regs + USI_CNT); 166 167 spin_unlock_irqrestore(&hw->lock, flags); 168} 169 170static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count) 171{ 172 return hw->tx ? hw->tx[count] : 0; 173} 174 175static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t) 176{ 177 struct nuc900_spi *hw = to_hw(spi); 178 179 hw->tx = t->tx_buf; 180 hw->rx = t->rx_buf; 181 hw->len = t->len; 182 hw->count = 0; 183 184 __raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0); 185 186 nuc900_spi_gobusy(hw); 187 188 wait_for_completion(&hw->done); 189 190 return hw->count; 191} 192 193static irqreturn_t nuc900_spi_irq(int irq, void *dev) 194{ 195 struct nuc900_spi *hw = dev; 196 unsigned int status; 197 unsigned int count = hw->count; 198 199 status = __raw_readl(hw->regs + USI_CNT); 200 __raw_writel(status, hw->regs + USI_CNT); 201 202 if (status & ENFLG) { 203 hw->count++; 204 205 if (hw->rx) 206 hw->rx[count] = __raw_readl(hw->regs + USI_RX0); 207 count++; 208 209 if (count < hw->len) { 210 __raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0); 211 nuc900_spi_gobusy(hw); 212 } else { 213 complete(&hw->done); 214 } 215 216 return IRQ_HANDLED; 217 } 218 219 complete(&hw->done); 220 return IRQ_HANDLED; 221} 222 223static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge) 224{ 225 unsigned int val; 226 unsigned long flags; 227 228 spin_lock_irqsave(&hw->lock, flags); 229 230 val = __raw_readl(hw->regs + USI_CNT); 231 232 if (edge) 233 val |= TXNEG; 234 else 235 val &= ~TXNEG; 236 __raw_writel(val, hw->regs + USI_CNT); 237 238 spin_unlock_irqrestore(&hw->lock, flags); 239} 240 241static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge) 242{ 243 unsigned int val; 244 unsigned long flags; 245 246 spin_lock_irqsave(&hw->lock, flags); 247 248 val = __raw_readl(hw->regs + USI_CNT); 249 250 if (edge) 251 val |= RXNEG; 252 else 253 val &= ~RXNEG; 254 __raw_writel(val, hw->regs + USI_CNT); 255 256 spin_unlock_irqrestore(&hw->lock, flags); 257} 258 259static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb) 260{ 261 unsigned int val; 262 unsigned long flags; 263 264 spin_lock_irqsave(&hw->lock, flags); 265 266 val = __raw_readl(hw->regs + USI_CNT); 267 268 if (lsb) 269 val |= LSB; 270 else 271 val &= ~LSB; 272 __raw_writel(val, hw->regs + USI_CNT); 273 274 spin_unlock_irqrestore(&hw->lock, flags); 275} 276 277static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep) 278{ 279 unsigned int val; 280 unsigned long flags; 281 282 spin_lock_irqsave(&hw->lock, flags); 283 284 val = __raw_readl(hw->regs + USI_CNT) & ~SLEEP; 285 286 if (sleep) 287 val |= (sleep << 12); 288 289 __raw_writel(val, hw->regs + USI_CNT); 290 291 spin_unlock_irqrestore(&hw->lock, flags); 292} 293 294static void nuc900_enable_int(struct nuc900_spi *hw) 295{ 296 unsigned int val; 297 unsigned long flags; 298 299 spin_lock_irqsave(&hw->lock, flags); 300 301 val = __raw_readl(hw->regs + USI_CNT); 302 303 val |= ENINT; 304 305 __raw_writel(val, hw->regs + USI_CNT); 306 307 spin_unlock_irqrestore(&hw->lock, flags); 308} 309 310static void nuc900_set_divider(struct nuc900_spi *hw) 311{ 312 __raw_writel(hw->pdata->divider, hw->regs + USI_DIV); 313} 314 315static void nuc900_init_spi(struct nuc900_spi *hw) 316{ 317 clk_enable(hw->clk); 318 spin_lock_init(&hw->lock); 319 320 nuc900_tx_edge(hw, hw->pdata->txneg); 321 nuc900_rx_edge(hw, hw->pdata->rxneg); 322 nuc900_send_first(hw, hw->pdata->lsb); 323 nuc900_set_sleep(hw, hw->pdata->sleep); 324 nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen); 325 nuc900_spi_setup_txnum(hw, hw->pdata->txnum); 326 nuc900_set_divider(hw); 327 nuc900_enable_int(hw); 328} 329 330static int nuc900_spi_probe(struct platform_device *pdev) 331{ 332 struct nuc900_spi *hw; 333 struct spi_master *master; 334 struct resource *res; 335 int err = 0; 336 337 master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi)); 338 if (master == NULL) { 339 dev_err(&pdev->dev, "No memory for spi_master\n"); 340 return -ENOMEM; 341 } 342 343 hw = spi_master_get_devdata(master); 344 hw->master = master; 345 hw->pdata = dev_get_platdata(&pdev->dev); 346 347 if (hw->pdata == NULL) { 348 dev_err(&pdev->dev, "No platform data supplied\n"); 349 err = -ENOENT; 350 goto err_pdata; 351 } 352 353 platform_set_drvdata(pdev, hw); 354 init_completion(&hw->done); 355 356 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; 357 if (hw->pdata->lsb) 358 master->mode_bits |= SPI_LSB_FIRST; 359 master->num_chipselect = hw->pdata->num_cs; 360 master->bus_num = hw->pdata->bus_num; 361 hw->bitbang.master = hw->master; 362 hw->bitbang.chipselect = nuc900_spi_chipsel; 363 hw->bitbang.txrx_bufs = nuc900_spi_txrx; 364 365 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 366 hw->regs = devm_ioremap_resource(&pdev->dev, res); 367 if (IS_ERR(hw->regs)) { 368 err = PTR_ERR(hw->regs); 369 goto err_pdata; 370 } 371 372 hw->irq = platform_get_irq(pdev, 0); 373 if (hw->irq < 0) { 374 dev_err(&pdev->dev, "No IRQ specified\n"); 375 err = -ENOENT; 376 goto err_pdata; 377 } 378 379 err = devm_request_irq(&pdev->dev, hw->irq, nuc900_spi_irq, 0, 380 pdev->name, hw); 381 if (err) { 382 dev_err(&pdev->dev, "Cannot claim IRQ\n"); 383 goto err_pdata; 384 } 385 386 hw->clk = devm_clk_get(&pdev->dev, "spi"); 387 if (IS_ERR(hw->clk)) { 388 dev_err(&pdev->dev, "No clock for device\n"); 389 err = PTR_ERR(hw->clk); 390 goto err_pdata; 391 } 392 393 mfp_set_groupg(&pdev->dev, NULL); 394 nuc900_init_spi(hw); 395 396 err = spi_bitbang_start(&hw->bitbang); 397 if (err) { 398 dev_err(&pdev->dev, "Failed to register SPI master\n"); 399 goto err_register; 400 } 401 402 return 0; 403 404err_register: 405 clk_disable(hw->clk); 406err_pdata: 407 spi_master_put(hw->master); 408 return err; 409} 410 411static int nuc900_spi_remove(struct platform_device *dev) 412{ 413 struct nuc900_spi *hw = platform_get_drvdata(dev); 414 415 spi_bitbang_stop(&hw->bitbang); 416 clk_disable(hw->clk); 417 spi_master_put(hw->master); 418 return 0; 419} 420 421static struct platform_driver nuc900_spi_driver = { 422 .probe = nuc900_spi_probe, 423 .remove = nuc900_spi_remove, 424 .driver = { 425 .name = "nuc900-spi", 426 }, 427}; 428module_platform_driver(nuc900_spi_driver); 429 430MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); 431MODULE_DESCRIPTION("nuc900 spi driver!"); 432MODULE_LICENSE("GPL"); 433MODULE_ALIAS("platform:nuc900-spi"); 434