Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9-rc3 470 lines 11 kB view raw
1/* 2 * This program is free software; you can redistribute it and/or modify it 3 * under the terms of the GNU General Public License version 2 as published 4 * by the Free Software Foundation. 5 * 6 * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com> 7 */ 8 9#include <linux/module.h> 10#include <linux/device.h> 11#include <linux/platform_device.h> 12#include <linux/spi/spi.h> 13#include <linux/delay.h> 14#include <linux/workqueue.h> 15#include <linux/of.h> 16#include <linux/of_platform.h> 17 18#include <lantiq_soc.h> 19 20#define DRV_NAME "sflash-falcon" 21 22#define FALCON_SPI_XFER_BEGIN (1 << 0) 23#define FALCON_SPI_XFER_END (1 << 1) 24 25/* Bus Read Configuration Register0 */ 26#define BUSRCON0 0x00000010 27/* Bus Write Configuration Register0 */ 28#define BUSWCON0 0x00000018 29/* Serial Flash Configuration Register */ 30#define SFCON 0x00000080 31/* Serial Flash Time Register */ 32#define SFTIME 0x00000084 33/* Serial Flash Status Register */ 34#define SFSTAT 0x00000088 35/* Serial Flash Command Register */ 36#define SFCMD 0x0000008C 37/* Serial Flash Address Register */ 38#define SFADDR 0x00000090 39/* Serial Flash Data Register */ 40#define SFDATA 0x00000094 41/* Serial Flash I/O Control Register */ 42#define SFIO 0x00000098 43/* EBU Clock Control Register */ 44#define EBUCC 0x000000C4 45 46/* Dummy Phase Length */ 47#define SFCMD_DUMLEN_OFFSET 16 48#define SFCMD_DUMLEN_MASK 0x000F0000 49/* Chip Select */ 50#define SFCMD_CS_OFFSET 24 51#define SFCMD_CS_MASK 0x07000000 52/* field offset */ 53#define SFCMD_ALEN_OFFSET 20 54#define SFCMD_ALEN_MASK 0x00700000 55/* SCK Rise-edge Position */ 56#define SFTIME_SCKR_POS_OFFSET 8 57#define SFTIME_SCKR_POS_MASK 0x00000F00 58/* SCK Period */ 59#define SFTIME_SCK_PER_OFFSET 0 60#define SFTIME_SCK_PER_MASK 0x0000000F 61/* SCK Fall-edge Position */ 62#define SFTIME_SCKF_POS_OFFSET 12 63#define SFTIME_SCKF_POS_MASK 0x0000F000 64/* Device Size */ 65#define SFCON_DEV_SIZE_A23_0 0x03000000 66#define SFCON_DEV_SIZE_MASK 0x0F000000 67/* Read Data Position */ 68#define SFTIME_RD_POS_MASK 0x000F0000 69/* Data Output */ 70#define SFIO_UNUSED_WD_MASK 0x0000000F 71/* Command Opcode mask */ 72#define SFCMD_OPC_MASK 0x000000FF 73/* dlen bytes of data to write */ 74#define SFCMD_DIR_WRITE 0x00000100 75/* Data Length offset */ 76#define SFCMD_DLEN_OFFSET 9 77/* Command Error */ 78#define SFSTAT_CMD_ERR 0x20000000 79/* Access Command Pending */ 80#define SFSTAT_CMD_PEND 0x00400000 81/* Frequency set to 100MHz. */ 82#define EBUCC_EBUDIV_SELF100 0x00000001 83/* Serial Flash */ 84#define BUSRCON0_AGEN_SERIAL_FLASH 0xF0000000 85/* 8-bit multiplexed */ 86#define BUSRCON0_PORTW_8_BIT_MUX 0x00000000 87/* Serial Flash */ 88#define BUSWCON0_AGEN_SERIAL_FLASH 0xF0000000 89/* Chip Select after opcode */ 90#define SFCMD_KEEP_CS_KEEP_SELECTED 0x00008000 91 92#define CLOCK_100M 100000000 93#define CLOCK_50M 50000000 94 95struct falcon_sflash { 96 u32 sfcmd; /* for caching of opcode, direction, ... */ 97 struct spi_master *master; 98}; 99 100int falcon_sflash_xfer(struct spi_device *spi, struct spi_transfer *t, 101 unsigned long flags) 102{ 103 struct device *dev = &spi->dev; 104 struct falcon_sflash *priv = spi_master_get_devdata(spi->master); 105 const u8 *txp = t->tx_buf; 106 u8 *rxp = t->rx_buf; 107 unsigned int bytelen = ((8 * t->len + 7) / 8); 108 unsigned int len, alen, dumlen; 109 u32 val; 110 enum { 111 state_init, 112 state_command_prepare, 113 state_write, 114 state_read, 115 state_disable_cs, 116 state_end 117 } state = state_init; 118 119 do { 120 switch (state) { 121 case state_init: /* detect phase of upper layer sequence */ 122 { 123 /* initial write ? */ 124 if (flags & FALCON_SPI_XFER_BEGIN) { 125 if (!txp) { 126 dev_err(dev, 127 "BEGIN without tx data!\n"); 128 return -ENODATA; 129 } 130 /* 131 * Prepare the parts of the sfcmd register, 132 * which should not change during a sequence! 133 * Only exception are the length fields, 134 * especially alen and dumlen. 135 */ 136 137 priv->sfcmd = ((spi->chip_select 138 << SFCMD_CS_OFFSET) 139 & SFCMD_CS_MASK); 140 priv->sfcmd |= SFCMD_KEEP_CS_KEEP_SELECTED; 141 priv->sfcmd |= *txp; 142 txp++; 143 bytelen--; 144 if (bytelen) { 145 /* 146 * more data: 147 * maybe address and/or dummy 148 */ 149 state = state_command_prepare; 150 break; 151 } else { 152 dev_dbg(dev, "write cmd %02X\n", 153 priv->sfcmd & SFCMD_OPC_MASK); 154 } 155 } 156 /* continued write ? */ 157 if (txp && bytelen) { 158 state = state_write; 159 break; 160 } 161 /* read data? */ 162 if (rxp && bytelen) { 163 state = state_read; 164 break; 165 } 166 /* end of sequence? */ 167 if (flags & FALCON_SPI_XFER_END) 168 state = state_disable_cs; 169 else 170 state = state_end; 171 break; 172 } 173 /* collect tx data for address and dummy phase */ 174 case state_command_prepare: 175 { 176 /* txp is valid, already checked */ 177 val = 0; 178 alen = 0; 179 dumlen = 0; 180 while (bytelen > 0) { 181 if (alen < 3) { 182 val = (val << 8) | (*txp++); 183 alen++; 184 } else if ((dumlen < 15) && (*txp == 0)) { 185 /* 186 * assume dummy bytes are set to 0 187 * from upper layer 188 */ 189 dumlen++; 190 txp++; 191 } else { 192 break; 193 } 194 bytelen--; 195 } 196 priv->sfcmd &= ~(SFCMD_ALEN_MASK | SFCMD_DUMLEN_MASK); 197 priv->sfcmd |= (alen << SFCMD_ALEN_OFFSET) | 198 (dumlen << SFCMD_DUMLEN_OFFSET); 199 if (alen > 0) 200 ltq_ebu_w32(val, SFADDR); 201 202 dev_dbg(dev, "wr %02X, alen=%d (addr=%06X) dlen=%d\n", 203 priv->sfcmd & SFCMD_OPC_MASK, 204 alen, val, dumlen); 205 206 if (bytelen > 0) { 207 /* continue with write */ 208 state = state_write; 209 } else if (flags & FALCON_SPI_XFER_END) { 210 /* end of sequence? */ 211 state = state_disable_cs; 212 } else { 213 /* 214 * go to end and expect another 215 * call (read or write) 216 */ 217 state = state_end; 218 } 219 break; 220 } 221 case state_write: 222 { 223 /* txp still valid */ 224 priv->sfcmd |= SFCMD_DIR_WRITE; 225 len = 0; 226 val = 0; 227 do { 228 if (bytelen--) 229 val |= (*txp++) << (8 * len++); 230 if ((flags & FALCON_SPI_XFER_END) 231 && (bytelen == 0)) { 232 priv->sfcmd &= 233 ~SFCMD_KEEP_CS_KEEP_SELECTED; 234 } 235 if ((len == 4) || (bytelen == 0)) { 236 ltq_ebu_w32(val, SFDATA); 237 ltq_ebu_w32(priv->sfcmd 238 | (len<<SFCMD_DLEN_OFFSET), 239 SFCMD); 240 len = 0; 241 val = 0; 242 priv->sfcmd &= ~(SFCMD_ALEN_MASK 243 | SFCMD_DUMLEN_MASK); 244 } 245 } while (bytelen); 246 state = state_end; 247 break; 248 } 249 case state_read: 250 { 251 /* read data */ 252 priv->sfcmd &= ~SFCMD_DIR_WRITE; 253 do { 254 if ((flags & FALCON_SPI_XFER_END) 255 && (bytelen <= 4)) { 256 priv->sfcmd &= 257 ~SFCMD_KEEP_CS_KEEP_SELECTED; 258 } 259 len = (bytelen > 4) ? 4 : bytelen; 260 bytelen -= len; 261 ltq_ebu_w32(priv->sfcmd 262 | (len << SFCMD_DLEN_OFFSET), SFCMD); 263 priv->sfcmd &= ~(SFCMD_ALEN_MASK 264 | SFCMD_DUMLEN_MASK); 265 do { 266 val = ltq_ebu_r32(SFSTAT); 267 if (val & SFSTAT_CMD_ERR) { 268 /* reset error status */ 269 dev_err(dev, "SFSTAT: CMD_ERR"); 270 dev_err(dev, " (%x)\n", val); 271 ltq_ebu_w32(SFSTAT_CMD_ERR, 272 SFSTAT); 273 return -EBADE; 274 } 275 } while (val & SFSTAT_CMD_PEND); 276 val = ltq_ebu_r32(SFDATA); 277 do { 278 *rxp = (val & 0xFF); 279 rxp++; 280 val >>= 8; 281 len--; 282 } while (len); 283 } while (bytelen); 284 state = state_end; 285 break; 286 } 287 case state_disable_cs: 288 { 289 priv->sfcmd &= ~SFCMD_KEEP_CS_KEEP_SELECTED; 290 ltq_ebu_w32(priv->sfcmd | (0 << SFCMD_DLEN_OFFSET), 291 SFCMD); 292 val = ltq_ebu_r32(SFSTAT); 293 if (val & SFSTAT_CMD_ERR) { 294 /* reset error status */ 295 dev_err(dev, "SFSTAT: CMD_ERR (%x)\n", val); 296 ltq_ebu_w32(SFSTAT_CMD_ERR, SFSTAT); 297 return -EBADE; 298 } 299 state = state_end; 300 break; 301 } 302 case state_end: 303 break; 304 } 305 } while (state != state_end); 306 307 return 0; 308} 309 310static int falcon_sflash_setup(struct spi_device *spi) 311{ 312 unsigned int i; 313 unsigned long flags; 314 315 if (spi->chip_select > 0) 316 return -ENODEV; 317 318 spin_lock_irqsave(&ebu_lock, flags); 319 320 if (spi->max_speed_hz >= CLOCK_100M) { 321 /* set EBU clock to 100 MHz */ 322 ltq_sys1_w32_mask(0, EBUCC_EBUDIV_SELF100, EBUCC); 323 i = 1; /* divider */ 324 } else { 325 /* set EBU clock to 50 MHz */ 326 ltq_sys1_w32_mask(EBUCC_EBUDIV_SELF100, 0, EBUCC); 327 328 /* search for suitable divider */ 329 for (i = 1; i < 7; i++) { 330 if (CLOCK_50M / i <= spi->max_speed_hz) 331 break; 332 } 333 } 334 335 /* setup period of serial clock */ 336 ltq_ebu_w32_mask(SFTIME_SCKF_POS_MASK 337 | SFTIME_SCKR_POS_MASK 338 | SFTIME_SCK_PER_MASK, 339 (i << SFTIME_SCKR_POS_OFFSET) 340 | (i << (SFTIME_SCK_PER_OFFSET + 1)), 341 SFTIME); 342 343 /* 344 * set some bits of unused_wd, to not trigger HOLD/WP 345 * signals on non QUAD flashes 346 */ 347 ltq_ebu_w32((SFIO_UNUSED_WD_MASK & (0x8 | 0x4)), SFIO); 348 349 ltq_ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX, 350 BUSRCON0); 351 ltq_ebu_w32(BUSWCON0_AGEN_SERIAL_FLASH, BUSWCON0); 352 /* set address wrap around to maximum for 24-bit addresses */ 353 ltq_ebu_w32_mask(SFCON_DEV_SIZE_MASK, SFCON_DEV_SIZE_A23_0, SFCON); 354 355 spin_unlock_irqrestore(&ebu_lock, flags); 356 357 return 0; 358} 359 360static int falcon_sflash_prepare_xfer(struct spi_master *master) 361{ 362 return 0; 363} 364 365static int falcon_sflash_unprepare_xfer(struct spi_master *master) 366{ 367 return 0; 368} 369 370static int falcon_sflash_xfer_one(struct spi_master *master, 371 struct spi_message *m) 372{ 373 struct falcon_sflash *priv = spi_master_get_devdata(master); 374 struct spi_transfer *t; 375 unsigned long spi_flags; 376 unsigned long flags; 377 int ret = 0; 378 379 priv->sfcmd = 0; 380 m->actual_length = 0; 381 382 spi_flags = FALCON_SPI_XFER_BEGIN; 383 list_for_each_entry(t, &m->transfers, transfer_list) { 384 if (list_is_last(&t->transfer_list, &m->transfers)) 385 spi_flags |= FALCON_SPI_XFER_END; 386 387 spin_lock_irqsave(&ebu_lock, flags); 388 ret = falcon_sflash_xfer(m->spi, t, spi_flags); 389 spin_unlock_irqrestore(&ebu_lock, flags); 390 391 if (ret) 392 break; 393 394 m->actual_length += t->len; 395 396 WARN_ON(t->delay_usecs || t->cs_change); 397 spi_flags = 0; 398 } 399 400 m->status = ret; 401 spi_finalize_current_message(master); 402 403 return 0; 404} 405 406static int falcon_sflash_probe(struct platform_device *pdev) 407{ 408 struct falcon_sflash *priv; 409 struct spi_master *master; 410 int ret; 411 412 if (ltq_boot_select() != BS_SPI) { 413 dev_err(&pdev->dev, "invalid bootstrap options\n"); 414 return -ENODEV; 415 } 416 417 master = spi_alloc_master(&pdev->dev, sizeof(*priv)); 418 if (!master) 419 return -ENOMEM; 420 421 priv = spi_master_get_devdata(master); 422 priv->master = master; 423 424 master->mode_bits = SPI_MODE_3; 425 master->num_chipselect = 1; 426 master->flags = SPI_MASTER_HALF_DUPLEX; 427 master->bus_num = -1; 428 master->setup = falcon_sflash_setup; 429 master->prepare_transfer_hardware = falcon_sflash_prepare_xfer; 430 master->transfer_one_message = falcon_sflash_xfer_one; 431 master->unprepare_transfer_hardware = falcon_sflash_unprepare_xfer; 432 master->dev.of_node = pdev->dev.of_node; 433 434 platform_set_drvdata(pdev, priv); 435 436 ret = spi_register_master(master); 437 if (ret) 438 spi_master_put(master); 439 return ret; 440} 441 442static int falcon_sflash_remove(struct platform_device *pdev) 443{ 444 struct falcon_sflash *priv = platform_get_drvdata(pdev); 445 446 spi_unregister_master(priv->master); 447 448 return 0; 449} 450 451static const struct of_device_id falcon_sflash_match[] = { 452 { .compatible = "lantiq,sflash-falcon" }, 453 {}, 454}; 455MODULE_DEVICE_TABLE(of, falcon_sflash_match); 456 457static struct platform_driver falcon_sflash_driver = { 458 .probe = falcon_sflash_probe, 459 .remove = falcon_sflash_remove, 460 .driver = { 461 .name = DRV_NAME, 462 .owner = THIS_MODULE, 463 .of_match_table = falcon_sflash_match, 464 } 465}; 466 467module_platform_driver(falcon_sflash_driver); 468 469MODULE_LICENSE("GPL"); 470MODULE_DESCRIPTION("Lantiq Falcon SPI/SFLASH controller driver");