18edbede9SRichard Röjfors /* 28edbede9SRichard Röjfors * timberdale.c timberdale FPGA MFD driver 38edbede9SRichard Röjfors * Copyright (c) 2009 Intel Corporation 48edbede9SRichard Röjfors * 58edbede9SRichard Röjfors * This program is free software; you can redistribute it and/or modify 68edbede9SRichard Röjfors * it under the terms of the GNU General Public License version 2 as 78edbede9SRichard Röjfors * published by the Free Software Foundation. 88edbede9SRichard Röjfors * 98edbede9SRichard Röjfors * This program is distributed in the hope that it will be useful, 108edbede9SRichard Röjfors * but WITHOUT ANY WARRANTY; without even the implied warranty of 118edbede9SRichard Röjfors * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 128edbede9SRichard Röjfors * GNU General Public License for more details. 138edbede9SRichard Röjfors * 148edbede9SRichard Röjfors * You should have received a copy of the GNU General Public License 158edbede9SRichard Röjfors * along with this program; if not, write to the Free Software 168edbede9SRichard Röjfors * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 178edbede9SRichard Röjfors */ 188edbede9SRichard Röjfors 198edbede9SRichard Röjfors /* Supports: 208edbede9SRichard Röjfors * Timberdale FPGA 218edbede9SRichard Röjfors */ 228edbede9SRichard Röjfors 238edbede9SRichard Röjfors #include <linux/kernel.h> 248edbede9SRichard Röjfors #include <linux/module.h> 258edbede9SRichard Röjfors #include <linux/pci.h> 268edbede9SRichard Röjfors #include <linux/msi.h> 278edbede9SRichard Röjfors #include <linux/mfd/core.h> 285a0e3ad6STejun Heo #include <linux/slab.h> 298edbede9SRichard Röjfors 308edbede9SRichard Röjfors #include <linux/timb_gpio.h> 318edbede9SRichard Röjfors 328edbede9SRichard Röjfors #include <linux/i2c.h> 338edbede9SRichard Röjfors #include <linux/i2c-ocores.h> 34d84027bcSRichard Röjfors #include <linux/i2c-xiic.h> 358edbede9SRichard Röjfors 368edbede9SRichard Röjfors #include <linux/spi/spi.h> 378edbede9SRichard Röjfors #include <linux/spi/xilinx_spi.h> 388edbede9SRichard Röjfors #include <linux/spi/max7301.h> 398edbede9SRichard Röjfors #include <linux/spi/mc33880.h> 408edbede9SRichard Röjfors 418fd70815SWolfram Sang #include <linux/platform_data/tsc2007.h> 42eb4b0ec7SMauro Carvalho Chehab #include <linux/platform_data/media/timb_radio.h> 43eb4b0ec7SMauro Carvalho Chehab #include <linux/platform_data/media/timb_video.h> 44071193ffSRichard Röjfors 45dc64f30fSRichard Röjfors #include <linux/timb_dma.h> 46dc64f30fSRichard Röjfors 476901ffd9SRichard Röjfors #include <linux/ks8842.h> 486901ffd9SRichard Röjfors 498edbede9SRichard Röjfors #include "timberdale.h" 508edbede9SRichard Röjfors 518edbede9SRichard Röjfors #define DRIVER_NAME "timberdale" 528edbede9SRichard Röjfors 538edbede9SRichard Röjfors struct timberdale_device { 548edbede9SRichard Röjfors resource_size_t ctl_mapbase; 558edbede9SRichard Röjfors unsigned char __iomem *ctl_membase; 568edbede9SRichard Röjfors struct { 578edbede9SRichard Röjfors u32 major; 588edbede9SRichard Röjfors u32 minor; 598edbede9SRichard Röjfors u32 config; 608edbede9SRichard Röjfors } fw; 618edbede9SRichard Röjfors }; 628edbede9SRichard Röjfors 638edbede9SRichard Röjfors /*--------------------------------------------------------------------------*/ 648edbede9SRichard Röjfors 658edbede9SRichard Röjfors static struct tsc2007_platform_data timberdale_tsc2007_platform_data = { 668edbede9SRichard Röjfors .model = 2003, 678edbede9SRichard Röjfors .x_plate_ohms = 100 688edbede9SRichard Röjfors }; 698edbede9SRichard Röjfors 708edbede9SRichard Röjfors static struct i2c_board_info timberdale_i2c_board_info[] = { 718edbede9SRichard Röjfors { 728edbede9SRichard Röjfors I2C_BOARD_INFO("tsc2007", 0x48), 738edbede9SRichard Röjfors .platform_data = &timberdale_tsc2007_platform_data, 748edbede9SRichard Röjfors .irq = IRQ_TIMBERDALE_TSC_INT 758edbede9SRichard Röjfors }, 768edbede9SRichard Röjfors }; 778edbede9SRichard Röjfors 78a9e9ce4cSBill Pemberton static struct xiic_i2c_platform_data 79d84027bcSRichard Röjfors timberdale_xiic_platform_data = { 80d84027bcSRichard Röjfors .devices = timberdale_i2c_board_info, 81d84027bcSRichard Röjfors .num_devices = ARRAY_SIZE(timberdale_i2c_board_info) 82d84027bcSRichard Röjfors }; 83d84027bcSRichard Röjfors 84a9e9ce4cSBill Pemberton static struct ocores_i2c_platform_data 858edbede9SRichard Röjfors timberdale_ocores_platform_data = { 86d739a464SJayachandran C .reg_shift = 2, 878edbede9SRichard Röjfors .clock_khz = 62500, 888edbede9SRichard Röjfors .devices = timberdale_i2c_board_info, 898edbede9SRichard Röjfors .num_devices = ARRAY_SIZE(timberdale_i2c_board_info) 908edbede9SRichard Röjfors }; 918edbede9SRichard Röjfors 92a73e5df1SBill Pemberton static const struct resource timberdale_xiic_resources[] = { 93d84027bcSRichard Röjfors { 94d84027bcSRichard Röjfors .start = XIICOFFSET, 95d84027bcSRichard Röjfors .end = XIICEND, 96d84027bcSRichard Röjfors .flags = IORESOURCE_MEM, 97d84027bcSRichard Röjfors }, 98d84027bcSRichard Röjfors { 99d84027bcSRichard Röjfors .start = IRQ_TIMBERDALE_I2C, 100d84027bcSRichard Röjfors .end = IRQ_TIMBERDALE_I2C, 101d84027bcSRichard Röjfors .flags = IORESOURCE_IRQ, 102d84027bcSRichard Röjfors }, 103d84027bcSRichard Röjfors }; 104d84027bcSRichard Röjfors 105a73e5df1SBill Pemberton static const struct resource timberdale_ocores_resources[] = { 1068edbede9SRichard Röjfors { 1078edbede9SRichard Röjfors .start = OCORESOFFSET, 1088edbede9SRichard Röjfors .end = OCORESEND, 1098edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 1108edbede9SRichard Röjfors }, 1118edbede9SRichard Röjfors { 1128edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_I2C, 1138edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_I2C, 1148edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 1158edbede9SRichard Röjfors }, 1168edbede9SRichard Röjfors }; 1178edbede9SRichard Röjfors 1184eaf4157SSachin Kamat static const struct max7301_platform_data timberdale_max7301_platform_data = { 1198edbede9SRichard Röjfors .base = 200 1208edbede9SRichard Röjfors }; 1218edbede9SRichard Röjfors 1224eaf4157SSachin Kamat static const struct mc33880_platform_data timberdale_mc33880_platform_data = { 1238edbede9SRichard Röjfors .base = 100 1248edbede9SRichard Röjfors }; 1258edbede9SRichard Röjfors 1268edbede9SRichard Röjfors static struct spi_board_info timberdale_spi_16bit_board_info[] = { 1278edbede9SRichard Röjfors { 1288edbede9SRichard Röjfors .modalias = "max7301", 1298edbede9SRichard Röjfors .max_speed_hz = 26000, 1308edbede9SRichard Röjfors .chip_select = 2, 1318edbede9SRichard Röjfors .mode = SPI_MODE_0, 1328edbede9SRichard Röjfors .platform_data = &timberdale_max7301_platform_data 1338edbede9SRichard Röjfors }, 1348edbede9SRichard Röjfors }; 1358edbede9SRichard Röjfors 1368edbede9SRichard Röjfors static struct spi_board_info timberdale_spi_8bit_board_info[] = { 1378edbede9SRichard Röjfors { 1388edbede9SRichard Röjfors .modalias = "mc33880", 1398edbede9SRichard Röjfors .max_speed_hz = 4000, 1408edbede9SRichard Röjfors .chip_select = 1, 1418edbede9SRichard Röjfors .mode = SPI_MODE_1, 1428edbede9SRichard Röjfors .platform_data = &timberdale_mc33880_platform_data 1438edbede9SRichard Röjfors }, 1448edbede9SRichard Röjfors }; 1458edbede9SRichard Röjfors 146a9e9ce4cSBill Pemberton static struct xspi_platform_data timberdale_xspi_platform_data = { 1478edbede9SRichard Röjfors .num_chipselect = 3, 1488edbede9SRichard Röjfors /* bits per word and devices will be filled in runtime depending 1498edbede9SRichard Röjfors * on the HW config 1508edbede9SRichard Röjfors */ 1518edbede9SRichard Röjfors }; 1528edbede9SRichard Röjfors 153a73e5df1SBill Pemberton static const struct resource timberdale_spi_resources[] = { 1548edbede9SRichard Röjfors { 1558edbede9SRichard Röjfors .start = SPIOFFSET, 1568edbede9SRichard Röjfors .end = SPIEND, 1578edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 1588edbede9SRichard Röjfors }, 1598edbede9SRichard Röjfors { 1608edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_SPI, 1618edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_SPI, 1628edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 1638edbede9SRichard Röjfors }, 1648edbede9SRichard Röjfors }; 1658edbede9SRichard Röjfors 166a9e9ce4cSBill Pemberton static struct ks8842_platform_data 1676901ffd9SRichard Röjfors timberdale_ks8842_platform_data = { 1686901ffd9SRichard Röjfors .rx_dma_channel = DMA_ETH_RX, 1696901ffd9SRichard Röjfors .tx_dma_channel = DMA_ETH_TX 1706901ffd9SRichard Röjfors }; 1716901ffd9SRichard Röjfors 172a73e5df1SBill Pemberton static const struct resource timberdale_eth_resources[] = { 1738edbede9SRichard Röjfors { 1748edbede9SRichard Röjfors .start = ETHOFFSET, 1758edbede9SRichard Röjfors .end = ETHEND, 1768edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 1778edbede9SRichard Röjfors }, 1788edbede9SRichard Röjfors { 1798edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_ETHSW_IF, 1808edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_ETHSW_IF, 1818edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 1828edbede9SRichard Röjfors }, 1838edbede9SRichard Röjfors }; 1848edbede9SRichard Röjfors 185a9e9ce4cSBill Pemberton static struct timbgpio_platform_data 1868edbede9SRichard Röjfors timberdale_gpio_platform_data = { 1878edbede9SRichard Röjfors .gpio_base = 0, 1888edbede9SRichard Röjfors .nr_pins = GPIO_NR_PINS, 1898edbede9SRichard Röjfors .irq_base = 200, 1908edbede9SRichard Röjfors }; 1918edbede9SRichard Röjfors 192a73e5df1SBill Pemberton static const struct resource timberdale_gpio_resources[] = { 1938edbede9SRichard Röjfors { 1948edbede9SRichard Röjfors .start = GPIOOFFSET, 1958edbede9SRichard Röjfors .end = GPIOEND, 1968edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 1978edbede9SRichard Röjfors }, 1988edbede9SRichard Röjfors { 1998edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_GPIO, 2008edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_GPIO, 2018edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 2028edbede9SRichard Röjfors }, 2038edbede9SRichard Röjfors }; 2048edbede9SRichard Röjfors 205a73e5df1SBill Pemberton static const struct resource timberdale_mlogicore_resources[] = { 2068edbede9SRichard Röjfors { 2078edbede9SRichard Röjfors .start = MLCOREOFFSET, 2088edbede9SRichard Röjfors .end = MLCOREEND, 2098edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 2108edbede9SRichard Röjfors }, 2118edbede9SRichard Röjfors { 2128edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_MLCORE, 2138edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_MLCORE, 2148edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 2158edbede9SRichard Röjfors }, 2168edbede9SRichard Röjfors { 2178edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_MLCORE_BUF, 2188edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_MLCORE_BUF, 2198edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 2208edbede9SRichard Röjfors }, 2218edbede9SRichard Röjfors }; 2228edbede9SRichard Röjfors 223a73e5df1SBill Pemberton static const struct resource timberdale_uart_resources[] = { 2248edbede9SRichard Röjfors { 2258edbede9SRichard Röjfors .start = UARTOFFSET, 2268edbede9SRichard Röjfors .end = UARTEND, 2278edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 2288edbede9SRichard Röjfors }, 2298edbede9SRichard Röjfors { 2308edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_UART, 2318edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_UART, 2328edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 2338edbede9SRichard Röjfors }, 2348edbede9SRichard Röjfors }; 2358edbede9SRichard Röjfors 236a73e5df1SBill Pemberton static const struct resource timberdale_uartlite_resources[] = { 2378edbede9SRichard Röjfors { 2388edbede9SRichard Röjfors .start = UARTLITEOFFSET, 2398edbede9SRichard Röjfors .end = UARTLITEEND, 2408edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 2418edbede9SRichard Röjfors }, 2428edbede9SRichard Röjfors { 2438edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_UARTLITE, 2448edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_UARTLITE, 2458edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 2468edbede9SRichard Röjfors }, 2478edbede9SRichard Röjfors }; 2488edbede9SRichard Röjfors 249a9e9ce4cSBill Pemberton static struct i2c_board_info timberdale_adv7180_i2c_board_info = { 250c091575cSRichard Röjfors /* Requires jumper JP9 to be off */ 251c091575cSRichard Röjfors I2C_BOARD_INFO("adv7180", 0x42 >> 1), 252c091575cSRichard Röjfors .irq = IRQ_TIMBERDALE_ADV7180 253c091575cSRichard Röjfors }; 254c091575cSRichard Röjfors 255a9e9ce4cSBill Pemberton static struct timb_video_platform_data 256c091575cSRichard Röjfors timberdale_video_platform_data = { 257c091575cSRichard Röjfors .dma_channel = DMA_VIDEO_RX, 258c091575cSRichard Röjfors .i2c_adapter = 0, 259c091575cSRichard Röjfors .encoder = { 260c091575cSRichard Röjfors .info = &timberdale_adv7180_i2c_board_info 261c091575cSRichard Röjfors } 262c091575cSRichard Röjfors }; 263c091575cSRichard Röjfors 264a73e5df1SBill Pemberton static const struct resource 265c091575cSRichard Röjfors timberdale_radio_resources[] = { 266071193ffSRichard Röjfors { 267071193ffSRichard Röjfors .start = RDSOFFSET, 268071193ffSRichard Röjfors .end = RDSEND, 269071193ffSRichard Röjfors .flags = IORESOURCE_MEM, 270071193ffSRichard Röjfors }, 271071193ffSRichard Röjfors { 272071193ffSRichard Röjfors .start = IRQ_TIMBERDALE_RDS, 273071193ffSRichard Röjfors .end = IRQ_TIMBERDALE_RDS, 274071193ffSRichard Röjfors .flags = IORESOURCE_IRQ, 275071193ffSRichard Röjfors }, 276071193ffSRichard Röjfors }; 277071193ffSRichard Röjfors 278a9e9ce4cSBill Pemberton static struct i2c_board_info timberdale_tef6868_i2c_board_info = { 279071193ffSRichard Röjfors I2C_BOARD_INFO("tef6862", 0x60) 280071193ffSRichard Röjfors }; 281071193ffSRichard Röjfors 282a9e9ce4cSBill Pemberton static struct i2c_board_info timberdale_saa7706_i2c_board_info = { 283071193ffSRichard Röjfors I2C_BOARD_INFO("saa7706h", 0x1C) 284071193ffSRichard Röjfors }; 285071193ffSRichard Röjfors 286a9e9ce4cSBill Pemberton static struct timb_radio_platform_data 287071193ffSRichard Röjfors timberdale_radio_platform_data = { 288071193ffSRichard Röjfors .i2c_adapter = 0, 2899cd49719SRichard Röjfors .tuner = &timberdale_tef6868_i2c_board_info, 2909cd49719SRichard Röjfors .dsp = &timberdale_saa7706_i2c_board_info 291071193ffSRichard Röjfors }; 292071193ffSRichard Röjfors 293a73e5df1SBill Pemberton static const struct resource timberdale_video_resources[] = { 294c091575cSRichard Röjfors { 295c091575cSRichard Röjfors .start = LOGIWOFFSET, 296c091575cSRichard Röjfors .end = LOGIWEND, 297c091575cSRichard Röjfors .flags = IORESOURCE_MEM, 298c091575cSRichard Röjfors }, 299c091575cSRichard Röjfors /* 300c091575cSRichard Röjfors note that the "frame buffer" is located in DMA area 301c091575cSRichard Röjfors starting at 0x1200000 302c091575cSRichard Röjfors */ 303c091575cSRichard Röjfors }; 304c091575cSRichard Röjfors 305a9e9ce4cSBill Pemberton static struct timb_dma_platform_data timb_dma_platform_data = { 306dc64f30fSRichard Röjfors .nr_channels = 10, 307dc64f30fSRichard Röjfors .channels = { 308dc64f30fSRichard Röjfors { 309dc64f30fSRichard Röjfors /* UART RX */ 310dc64f30fSRichard Röjfors .rx = true, 311dc64f30fSRichard Röjfors .descriptors = 2, 312dc64f30fSRichard Röjfors .descriptor_elements = 1 313dc64f30fSRichard Röjfors }, 314dc64f30fSRichard Röjfors { 315dc64f30fSRichard Röjfors /* UART TX */ 316dc64f30fSRichard Röjfors .rx = false, 317dc64f30fSRichard Röjfors .descriptors = 2, 318dc64f30fSRichard Röjfors .descriptor_elements = 1 319dc64f30fSRichard Röjfors }, 320dc64f30fSRichard Röjfors { 321dc64f30fSRichard Röjfors /* MLB RX */ 322dc64f30fSRichard Röjfors .rx = true, 323dc64f30fSRichard Röjfors .descriptors = 2, 324dc64f30fSRichard Röjfors .descriptor_elements = 1 325dc64f30fSRichard Röjfors }, 326dc64f30fSRichard Röjfors { 327dc64f30fSRichard Röjfors /* MLB TX */ 328dc64f30fSRichard Röjfors .rx = false, 329dc64f30fSRichard Röjfors .descriptors = 2, 330dc64f30fSRichard Röjfors .descriptor_elements = 1 331dc64f30fSRichard Röjfors }, 332dc64f30fSRichard Röjfors { 333dc64f30fSRichard Röjfors /* Video RX */ 334dc64f30fSRichard Röjfors .rx = true, 335dc64f30fSRichard Röjfors .bytes_per_line = 1440, 336dc64f30fSRichard Röjfors .descriptors = 2, 337dc64f30fSRichard Röjfors .descriptor_elements = 16 338dc64f30fSRichard Röjfors }, 339dc64f30fSRichard Röjfors { 340dc64f30fSRichard Röjfors /* Video framedrop */ 341dc64f30fSRichard Röjfors }, 342dc64f30fSRichard Röjfors { 343dc64f30fSRichard Röjfors /* SDHCI RX */ 344dc64f30fSRichard Röjfors .rx = true, 345dc64f30fSRichard Röjfors }, 346dc64f30fSRichard Röjfors { 347dc64f30fSRichard Röjfors /* SDHCI TX */ 348dc64f30fSRichard Röjfors }, 349dc64f30fSRichard Röjfors { 350dc64f30fSRichard Röjfors /* ETH RX */ 351dc64f30fSRichard Röjfors .rx = true, 352dc64f30fSRichard Röjfors .descriptors = 2, 353dc64f30fSRichard Röjfors .descriptor_elements = 1 354dc64f30fSRichard Röjfors }, 355dc64f30fSRichard Röjfors { 356dc64f30fSRichard Röjfors /* ETH TX */ 357dc64f30fSRichard Röjfors .rx = false, 358dc64f30fSRichard Röjfors .descriptors = 2, 359dc64f30fSRichard Röjfors .descriptor_elements = 1 360dc64f30fSRichard Röjfors }, 361dc64f30fSRichard Röjfors } 362dc64f30fSRichard Röjfors }; 363dc64f30fSRichard Röjfors 364a73e5df1SBill Pemberton static const struct resource timberdale_dma_resources[] = { 3658edbede9SRichard Röjfors { 3668edbede9SRichard Röjfors .start = DMAOFFSET, 3678edbede9SRichard Röjfors .end = DMAEND, 3688edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 3698edbede9SRichard Röjfors }, 3708edbede9SRichard Röjfors { 3718edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_DMA, 3728edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_DMA, 3738edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 3748edbede9SRichard Röjfors }, 3758edbede9SRichard Röjfors }; 3768edbede9SRichard Röjfors 3775ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar0_cfg0[] = { 3788edbede9SRichard Röjfors { 379dc64f30fSRichard Röjfors .name = "timb-dma", 380dc64f30fSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_dma_resources), 381dc64f30fSRichard Röjfors .resources = timberdale_dma_resources, 3823271d382SSamuel Ortiz .platform_data = &timb_dma_platform_data, 3833271d382SSamuel Ortiz .pdata_size = sizeof(timb_dma_platform_data), 384dc64f30fSRichard Röjfors }, 385dc64f30fSRichard Röjfors { 3868edbede9SRichard Röjfors .name = "timb-uart", 3878edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_uart_resources), 3888edbede9SRichard Röjfors .resources = timberdale_uart_resources, 3898edbede9SRichard Röjfors }, 3908edbede9SRichard Röjfors { 391d84027bcSRichard Röjfors .name = "xiic-i2c", 392d84027bcSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_xiic_resources), 393d84027bcSRichard Röjfors .resources = timberdale_xiic_resources, 3943271d382SSamuel Ortiz .platform_data = &timberdale_xiic_platform_data, 3953271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_xiic_platform_data), 396d84027bcSRichard Röjfors }, 397d84027bcSRichard Röjfors { 3988edbede9SRichard Röjfors .name = "timb-gpio", 3998edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_gpio_resources), 4008edbede9SRichard Röjfors .resources = timberdale_gpio_resources, 4013271d382SSamuel Ortiz .platform_data = &timberdale_gpio_platform_data, 4023271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_gpio_platform_data), 4038edbede9SRichard Röjfors }, 4048edbede9SRichard Röjfors { 405c091575cSRichard Röjfors .name = "timb-video", 406c091575cSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_video_resources), 407c091575cSRichard Röjfors .resources = timberdale_video_resources, 4083271d382SSamuel Ortiz .platform_data = &timberdale_video_platform_data, 4093271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_video_platform_data), 410c091575cSRichard Röjfors }, 411c091575cSRichard Röjfors { 412071193ffSRichard Röjfors .name = "timb-radio", 413071193ffSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_radio_resources), 414071193ffSRichard Röjfors .resources = timberdale_radio_resources, 4153271d382SSamuel Ortiz .platform_data = &timberdale_radio_platform_data, 4163271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_radio_platform_data), 417071193ffSRichard Röjfors }, 418071193ffSRichard Röjfors { 4198edbede9SRichard Röjfors .name = "xilinx_spi", 4208edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_spi_resources), 4218edbede9SRichard Röjfors .resources = timberdale_spi_resources, 4223271d382SSamuel Ortiz .platform_data = &timberdale_xspi_platform_data, 4233271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_xspi_platform_data), 4248edbede9SRichard Röjfors }, 4258edbede9SRichard Röjfors { 4268edbede9SRichard Röjfors .name = "ks8842", 4278edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_eth_resources), 4288edbede9SRichard Röjfors .resources = timberdale_eth_resources, 4293271d382SSamuel Ortiz .platform_data = &timberdale_ks8842_platform_data, 4303271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_ks8842_platform_data), 4318edbede9SRichard Röjfors }, 432dc64f30fSRichard Röjfors }; 433dc64f30fSRichard Röjfors 4345ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar0_cfg1[] = { 4358edbede9SRichard Röjfors { 4368edbede9SRichard Röjfors .name = "timb-dma", 4378edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_dma_resources), 4388edbede9SRichard Röjfors .resources = timberdale_dma_resources, 4393271d382SSamuel Ortiz .platform_data = &timb_dma_platform_data, 4403271d382SSamuel Ortiz .pdata_size = sizeof(timb_dma_platform_data), 4418edbede9SRichard Röjfors }, 4428edbede9SRichard Röjfors { 4438edbede9SRichard Röjfors .name = "timb-uart", 4448edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_uart_resources), 4458edbede9SRichard Röjfors .resources = timberdale_uart_resources, 4468edbede9SRichard Röjfors }, 4478edbede9SRichard Röjfors { 4488edbede9SRichard Röjfors .name = "uartlite", 4498edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_uartlite_resources), 4508edbede9SRichard Röjfors .resources = timberdale_uartlite_resources, 4518edbede9SRichard Röjfors }, 4528edbede9SRichard Röjfors { 453d84027bcSRichard Röjfors .name = "xiic-i2c", 454d84027bcSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_xiic_resources), 455d84027bcSRichard Röjfors .resources = timberdale_xiic_resources, 4563271d382SSamuel Ortiz .platform_data = &timberdale_xiic_platform_data, 4573271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_xiic_platform_data), 458d84027bcSRichard Röjfors }, 459d84027bcSRichard Röjfors { 4608edbede9SRichard Röjfors .name = "timb-gpio", 4618edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_gpio_resources), 4628edbede9SRichard Röjfors .resources = timberdale_gpio_resources, 4633271d382SSamuel Ortiz .platform_data = &timberdale_gpio_platform_data, 4643271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_gpio_platform_data), 4658edbede9SRichard Röjfors }, 4668edbede9SRichard Röjfors { 4678edbede9SRichard Röjfors .name = "timb-mlogicore", 4688edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_mlogicore_resources), 4698edbede9SRichard Röjfors .resources = timberdale_mlogicore_resources, 4708edbede9SRichard Röjfors }, 4718edbede9SRichard Röjfors { 472c091575cSRichard Röjfors .name = "timb-video", 473c091575cSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_video_resources), 474c091575cSRichard Röjfors .resources = timberdale_video_resources, 4753271d382SSamuel Ortiz .platform_data = &timberdale_video_platform_data, 4763271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_video_platform_data), 477c091575cSRichard Röjfors }, 478c091575cSRichard Röjfors { 479071193ffSRichard Röjfors .name = "timb-radio", 480071193ffSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_radio_resources), 481071193ffSRichard Röjfors .resources = timberdale_radio_resources, 4823271d382SSamuel Ortiz .platform_data = &timberdale_radio_platform_data, 4833271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_radio_platform_data), 484071193ffSRichard Röjfors }, 485071193ffSRichard Röjfors { 4868edbede9SRichard Röjfors .name = "xilinx_spi", 4878edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_spi_resources), 4888edbede9SRichard Röjfors .resources = timberdale_spi_resources, 4893271d382SSamuel Ortiz .platform_data = &timberdale_xspi_platform_data, 4903271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_xspi_platform_data), 4918edbede9SRichard Röjfors }, 4928edbede9SRichard Röjfors { 4938edbede9SRichard Röjfors .name = "ks8842", 4948edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_eth_resources), 4958edbede9SRichard Röjfors .resources = timberdale_eth_resources, 4963271d382SSamuel Ortiz .platform_data = &timberdale_ks8842_platform_data, 4973271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_ks8842_platform_data), 4988edbede9SRichard Röjfors }, 499dc64f30fSRichard Röjfors }; 500dc64f30fSRichard Röjfors 5015ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar0_cfg2[] = { 5028edbede9SRichard Röjfors { 5038edbede9SRichard Röjfors .name = "timb-dma", 5048edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_dma_resources), 5058edbede9SRichard Röjfors .resources = timberdale_dma_resources, 5063271d382SSamuel Ortiz .platform_data = &timb_dma_platform_data, 5073271d382SSamuel Ortiz .pdata_size = sizeof(timb_dma_platform_data), 5088edbede9SRichard Röjfors }, 5098edbede9SRichard Röjfors { 5108edbede9SRichard Röjfors .name = "timb-uart", 5118edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_uart_resources), 5128edbede9SRichard Röjfors .resources = timberdale_uart_resources, 5138edbede9SRichard Röjfors }, 5148edbede9SRichard Röjfors { 515d84027bcSRichard Röjfors .name = "xiic-i2c", 516d84027bcSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_xiic_resources), 517d84027bcSRichard Röjfors .resources = timberdale_xiic_resources, 5183271d382SSamuel Ortiz .platform_data = &timberdale_xiic_platform_data, 5193271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_xiic_platform_data), 520d84027bcSRichard Röjfors }, 521d84027bcSRichard Röjfors { 5228edbede9SRichard Röjfors .name = "timb-gpio", 5238edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_gpio_resources), 5248edbede9SRichard Röjfors .resources = timberdale_gpio_resources, 5253271d382SSamuel Ortiz .platform_data = &timberdale_gpio_platform_data, 5263271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_gpio_platform_data), 5278edbede9SRichard Röjfors }, 5288edbede9SRichard Röjfors { 529c091575cSRichard Röjfors .name = "timb-video", 530c091575cSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_video_resources), 531c091575cSRichard Röjfors .resources = timberdale_video_resources, 5323271d382SSamuel Ortiz .platform_data = &timberdale_video_platform_data, 5333271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_video_platform_data), 534c091575cSRichard Röjfors }, 535c091575cSRichard Röjfors { 536071193ffSRichard Röjfors .name = "timb-radio", 537071193ffSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_radio_resources), 538071193ffSRichard Röjfors .resources = timberdale_radio_resources, 5393271d382SSamuel Ortiz .platform_data = &timberdale_radio_platform_data, 5403271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_radio_platform_data), 541071193ffSRichard Röjfors }, 542071193ffSRichard Röjfors { 5438edbede9SRichard Röjfors .name = "xilinx_spi", 5448edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_spi_resources), 5458edbede9SRichard Röjfors .resources = timberdale_spi_resources, 5463271d382SSamuel Ortiz .platform_data = &timberdale_xspi_platform_data, 5473271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_xspi_platform_data), 5488edbede9SRichard Röjfors }, 549dc64f30fSRichard Röjfors }; 550dc64f30fSRichard Röjfors 5515ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar0_cfg3[] = { 5528edbede9SRichard Röjfors { 5538edbede9SRichard Röjfors .name = "timb-dma", 5548edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_dma_resources), 5558edbede9SRichard Röjfors .resources = timberdale_dma_resources, 5563271d382SSamuel Ortiz .platform_data = &timb_dma_platform_data, 5573271d382SSamuel Ortiz .pdata_size = sizeof(timb_dma_platform_data), 5588edbede9SRichard Röjfors }, 5598edbede9SRichard Röjfors { 5608edbede9SRichard Röjfors .name = "timb-uart", 5618edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_uart_resources), 5628edbede9SRichard Röjfors .resources = timberdale_uart_resources, 5638edbede9SRichard Röjfors }, 5648edbede9SRichard Röjfors { 5658edbede9SRichard Röjfors .name = "ocores-i2c", 5668edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_ocores_resources), 5678edbede9SRichard Röjfors .resources = timberdale_ocores_resources, 5683271d382SSamuel Ortiz .platform_data = &timberdale_ocores_platform_data, 5693271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_ocores_platform_data), 5708edbede9SRichard Röjfors }, 5718edbede9SRichard Röjfors { 5728edbede9SRichard Röjfors .name = "timb-gpio", 5738edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_gpio_resources), 5748edbede9SRichard Röjfors .resources = timberdale_gpio_resources, 5753271d382SSamuel Ortiz .platform_data = &timberdale_gpio_platform_data, 5763271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_gpio_platform_data), 5778edbede9SRichard Röjfors }, 5788edbede9SRichard Röjfors { 579c091575cSRichard Röjfors .name = "timb-video", 580c091575cSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_video_resources), 581c091575cSRichard Röjfors .resources = timberdale_video_resources, 5823271d382SSamuel Ortiz .platform_data = &timberdale_video_platform_data, 5833271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_video_platform_data), 584c091575cSRichard Röjfors }, 585c091575cSRichard Röjfors { 586071193ffSRichard Röjfors .name = "timb-radio", 587071193ffSRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_radio_resources), 588071193ffSRichard Röjfors .resources = timberdale_radio_resources, 5893271d382SSamuel Ortiz .platform_data = &timberdale_radio_platform_data, 5903271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_radio_platform_data), 591071193ffSRichard Röjfors }, 592071193ffSRichard Röjfors { 5938edbede9SRichard Röjfors .name = "xilinx_spi", 5948edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_spi_resources), 5958edbede9SRichard Röjfors .resources = timberdale_spi_resources, 5963271d382SSamuel Ortiz .platform_data = &timberdale_xspi_platform_data, 5973271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_xspi_platform_data), 5988edbede9SRichard Röjfors }, 5998edbede9SRichard Röjfors { 6008edbede9SRichard Röjfors .name = "ks8842", 6018edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_eth_resources), 6028edbede9SRichard Röjfors .resources = timberdale_eth_resources, 6033271d382SSamuel Ortiz .platform_data = &timberdale_ks8842_platform_data, 6043271d382SSamuel Ortiz .pdata_size = sizeof(timberdale_ks8842_platform_data), 6058edbede9SRichard Röjfors }, 6068edbede9SRichard Röjfors }; 6078edbede9SRichard Röjfors 608a73e5df1SBill Pemberton static const struct resource timberdale_sdhc_resources[] = { 6098edbede9SRichard Röjfors /* located in bar 1 and bar 2 */ 6108edbede9SRichard Röjfors { 6118edbede9SRichard Röjfors .start = SDHC0OFFSET, 6128edbede9SRichard Röjfors .end = SDHC0END, 6138edbede9SRichard Röjfors .flags = IORESOURCE_MEM, 6148edbede9SRichard Röjfors }, 6158edbede9SRichard Röjfors { 6168edbede9SRichard Röjfors .start = IRQ_TIMBERDALE_SDHC, 6178edbede9SRichard Röjfors .end = IRQ_TIMBERDALE_SDHC, 6188edbede9SRichard Röjfors .flags = IORESOURCE_IRQ, 6198edbede9SRichard Röjfors }, 6208edbede9SRichard Röjfors }; 6218edbede9SRichard Röjfors 6225ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar1[] = { 6238edbede9SRichard Röjfors { 6248edbede9SRichard Röjfors .name = "sdhci", 6258edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_sdhc_resources), 6268edbede9SRichard Röjfors .resources = timberdale_sdhc_resources, 6278edbede9SRichard Röjfors }, 6288edbede9SRichard Röjfors }; 6298edbede9SRichard Röjfors 6305ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar2[] = { 6318edbede9SRichard Röjfors { 6328edbede9SRichard Röjfors .name = "sdhci", 6338edbede9SRichard Röjfors .num_resources = ARRAY_SIZE(timberdale_sdhc_resources), 6348edbede9SRichard Röjfors .resources = timberdale_sdhc_resources, 6358edbede9SRichard Röjfors }, 6368edbede9SRichard Röjfors }; 6378edbede9SRichard Röjfors 6388edbede9SRichard Röjfors static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, 6398edbede9SRichard Röjfors char *buf) 6408edbede9SRichard Röjfors { 6418edbede9SRichard Röjfors struct pci_dev *pdev = to_pci_dev(dev); 6428edbede9SRichard Röjfors struct timberdale_device *priv = pci_get_drvdata(pdev); 6438edbede9SRichard Röjfors 6448edbede9SRichard Röjfors return sprintf(buf, "%d.%d.%d\n", priv->fw.major, priv->fw.minor, 6458edbede9SRichard Röjfors priv->fw.config); 6468edbede9SRichard Röjfors } 6478edbede9SRichard Röjfors 6488edbede9SRichard Röjfors static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); 6498edbede9SRichard Röjfors 6508edbede9SRichard Röjfors /*--------------------------------------------------------------------------*/ 6518edbede9SRichard Röjfors 652f791be49SBill Pemberton static int timb_probe(struct pci_dev *dev, 6538edbede9SRichard Röjfors const struct pci_device_id *id) 6548edbede9SRichard Röjfors { 6558edbede9SRichard Röjfors struct timberdale_device *priv; 6568edbede9SRichard Röjfors int err, i; 6578edbede9SRichard Röjfors resource_size_t mapbase; 6588edbede9SRichard Röjfors struct msix_entry *msix_entries = NULL; 6598edbede9SRichard Röjfors u8 ip_setup; 6608edbede9SRichard Röjfors 6618edbede9SRichard Röjfors priv = kzalloc(sizeof(*priv), GFP_KERNEL); 6628edbede9SRichard Röjfors if (!priv) 6638edbede9SRichard Röjfors return -ENOMEM; 6648edbede9SRichard Röjfors 6658edbede9SRichard Röjfors pci_set_drvdata(dev, priv); 6668edbede9SRichard Röjfors 6678edbede9SRichard Röjfors err = pci_enable_device(dev); 6688edbede9SRichard Röjfors if (err) 6698edbede9SRichard Röjfors goto err_enable; 6708edbede9SRichard Röjfors 6718edbede9SRichard Röjfors mapbase = pci_resource_start(dev, 0); 6728edbede9SRichard Röjfors if (!mapbase) { 6738edbede9SRichard Röjfors dev_err(&dev->dev, "No resource\n"); 6748edbede9SRichard Röjfors goto err_start; 6758edbede9SRichard Röjfors } 6768edbede9SRichard Röjfors 6778edbede9SRichard Röjfors /* create a resource for the PCI master register */ 6788edbede9SRichard Röjfors priv->ctl_mapbase = mapbase + CHIPCTLOFFSET; 6798edbede9SRichard Röjfors if (!request_mem_region(priv->ctl_mapbase, CHIPCTLSIZE, "timb-ctl")) { 6808edbede9SRichard Röjfors dev_err(&dev->dev, "Failed to request ctl mem\n"); 6817902fe8cSJingoo Han goto err_start; 6828edbede9SRichard Röjfors } 6838edbede9SRichard Röjfors 6848edbede9SRichard Röjfors priv->ctl_membase = ioremap(priv->ctl_mapbase, CHIPCTLSIZE); 6858edbede9SRichard Röjfors if (!priv->ctl_membase) { 6868edbede9SRichard Röjfors dev_err(&dev->dev, "ioremap failed for ctl mem\n"); 6878edbede9SRichard Röjfors goto err_ioremap; 6888edbede9SRichard Röjfors } 6898edbede9SRichard Röjfors 6908edbede9SRichard Röjfors /* read the HW config */ 6918edbede9SRichard Röjfors priv->fw.major = ioread32(priv->ctl_membase + TIMB_REV_MAJOR); 6928edbede9SRichard Röjfors priv->fw.minor = ioread32(priv->ctl_membase + TIMB_REV_MINOR); 6938edbede9SRichard Röjfors priv->fw.config = ioread32(priv->ctl_membase + TIMB_HW_CONFIG); 6948edbede9SRichard Röjfors 6958edbede9SRichard Röjfors if (priv->fw.major > TIMB_SUPPORTED_MAJOR) { 6968edbede9SRichard Röjfors dev_err(&dev->dev, "The driver supports an older " 6978edbede9SRichard Röjfors "version of the FPGA, please update the driver to " 6988edbede9SRichard Röjfors "support %d.%d\n", priv->fw.major, priv->fw.minor); 699981c65a9SJulia Lawall goto err_config; 7008edbede9SRichard Röjfors } 7018edbede9SRichard Röjfors if (priv->fw.major < TIMB_SUPPORTED_MAJOR || 7028edbede9SRichard Röjfors priv->fw.minor < TIMB_REQUIRED_MINOR) { 7038edbede9SRichard Röjfors dev_err(&dev->dev, "The FPGA image is too old (%d.%d), " 7048edbede9SRichard Röjfors "please upgrade the FPGA to at least: %d.%d\n", 7058edbede9SRichard Röjfors priv->fw.major, priv->fw.minor, 7068edbede9SRichard Röjfors TIMB_SUPPORTED_MAJOR, TIMB_REQUIRED_MINOR); 707981c65a9SJulia Lawall goto err_config; 7088edbede9SRichard Röjfors } 7098edbede9SRichard Röjfors 7108edbede9SRichard Röjfors msix_entries = kzalloc(TIMBERDALE_NR_IRQS * sizeof(*msix_entries), 7118edbede9SRichard Röjfors GFP_KERNEL); 7128edbede9SRichard Röjfors if (!msix_entries) 713981c65a9SJulia Lawall goto err_config; 7148edbede9SRichard Röjfors 7158edbede9SRichard Röjfors for (i = 0; i < TIMBERDALE_NR_IRQS; i++) 7168edbede9SRichard Röjfors msix_entries[i].entry = i; 7178edbede9SRichard Röjfors 718471212d9SAlexander Gordeev err = pci_enable_msix_exact(dev, msix_entries, TIMBERDALE_NR_IRQS); 7198edbede9SRichard Röjfors if (err) { 7208edbede9SRichard Röjfors dev_err(&dev->dev, 7218edbede9SRichard Röjfors "MSI-X init failed: %d, expected entries: %d\n", 7228edbede9SRichard Röjfors err, TIMBERDALE_NR_IRQS); 7238edbede9SRichard Röjfors goto err_msix; 7248edbede9SRichard Röjfors } 7258edbede9SRichard Röjfors 7268edbede9SRichard Röjfors err = device_create_file(&dev->dev, &dev_attr_fw_ver); 7278edbede9SRichard Röjfors if (err) 7288edbede9SRichard Röjfors goto err_create_file; 7298edbede9SRichard Röjfors 7308edbede9SRichard Röjfors /* Reset all FPGA PLB peripherals */ 7318edbede9SRichard Röjfors iowrite32(0x1, priv->ctl_membase + TIMB_SW_RST); 7328edbede9SRichard Röjfors 7338edbede9SRichard Röjfors /* update IRQ offsets in I2C board info */ 7348edbede9SRichard Röjfors for (i = 0; i < ARRAY_SIZE(timberdale_i2c_board_info); i++) 7358edbede9SRichard Röjfors timberdale_i2c_board_info[i].irq = 7368edbede9SRichard Röjfors msix_entries[timberdale_i2c_board_info[i].irq].vector; 7378edbede9SRichard Röjfors 7388edbede9SRichard Röjfors /* Update the SPI configuration depending on the HW (8 or 16 bit) */ 7398edbede9SRichard Röjfors if (priv->fw.config & TIMB_HW_CONFIG_SPI_8BIT) { 7408edbede9SRichard Röjfors timberdale_xspi_platform_data.bits_per_word = 8; 7418edbede9SRichard Röjfors timberdale_xspi_platform_data.devices = 7428edbede9SRichard Röjfors timberdale_spi_8bit_board_info; 7438edbede9SRichard Röjfors timberdale_xspi_platform_data.num_devices = 7448edbede9SRichard Röjfors ARRAY_SIZE(timberdale_spi_8bit_board_info); 7458edbede9SRichard Röjfors } else { 7468edbede9SRichard Röjfors timberdale_xspi_platform_data.bits_per_word = 16; 7478edbede9SRichard Röjfors timberdale_xspi_platform_data.devices = 7488edbede9SRichard Röjfors timberdale_spi_16bit_board_info; 7498edbede9SRichard Röjfors timberdale_xspi_platform_data.num_devices = 7508edbede9SRichard Röjfors ARRAY_SIZE(timberdale_spi_16bit_board_info); 7518edbede9SRichard Röjfors } 7528edbede9SRichard Röjfors 7538edbede9SRichard Röjfors ip_setup = priv->fw.config & TIMB_HW_VER_MASK; 7548edbede9SRichard Röjfors switch (ip_setup) { 7558edbede9SRichard Röjfors case TIMB_HW_VER0: 7568edbede9SRichard Röjfors err = mfd_add_devices(&dev->dev, -1, 7578edbede9SRichard Röjfors timberdale_cells_bar0_cfg0, 7588edbede9SRichard Röjfors ARRAY_SIZE(timberdale_cells_bar0_cfg0), 7590848c94fSMark Brown &dev->resource[0], msix_entries[0].vector, NULL); 7608edbede9SRichard Röjfors break; 7618edbede9SRichard Röjfors case TIMB_HW_VER1: 7628edbede9SRichard Röjfors err = mfd_add_devices(&dev->dev, -1, 7638edbede9SRichard Röjfors timberdale_cells_bar0_cfg1, 7648edbede9SRichard Röjfors ARRAY_SIZE(timberdale_cells_bar0_cfg1), 7650848c94fSMark Brown &dev->resource[0], msix_entries[0].vector, NULL); 7668edbede9SRichard Röjfors break; 7678edbede9SRichard Röjfors case TIMB_HW_VER2: 7688edbede9SRichard Röjfors err = mfd_add_devices(&dev->dev, -1, 7698edbede9SRichard Röjfors timberdale_cells_bar0_cfg2, 7708edbede9SRichard Röjfors ARRAY_SIZE(timberdale_cells_bar0_cfg2), 7710848c94fSMark Brown &dev->resource[0], msix_entries[0].vector, NULL); 7728edbede9SRichard Röjfors break; 7738edbede9SRichard Röjfors case TIMB_HW_VER3: 7748edbede9SRichard Röjfors err = mfd_add_devices(&dev->dev, -1, 7758edbede9SRichard Röjfors timberdale_cells_bar0_cfg3, 7768edbede9SRichard Röjfors ARRAY_SIZE(timberdale_cells_bar0_cfg3), 7770848c94fSMark Brown &dev->resource[0], msix_entries[0].vector, NULL); 7788edbede9SRichard Röjfors break; 7798edbede9SRichard Röjfors default: 7805588bd59SColin Ian King dev_err(&dev->dev, "Unknown IP setup: %d.%d.%d\n", 7818edbede9SRichard Röjfors priv->fw.major, priv->fw.minor, ip_setup); 7828edbede9SRichard Röjfors err = -ENODEV; 7838edbede9SRichard Röjfors goto err_mfd; 7848edbede9SRichard Röjfors } 7858edbede9SRichard Röjfors 7868edbede9SRichard Röjfors if (err) { 7878edbede9SRichard Röjfors dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); 7888edbede9SRichard Röjfors goto err_mfd; 7898edbede9SRichard Röjfors } 7908edbede9SRichard Röjfors 7918edbede9SRichard Röjfors err = mfd_add_devices(&dev->dev, 0, 7928edbede9SRichard Röjfors timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1), 7930848c94fSMark Brown &dev->resource[1], msix_entries[0].vector, NULL); 7948edbede9SRichard Röjfors if (err) { 7958edbede9SRichard Röjfors dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); 7968edbede9SRichard Röjfors goto err_mfd2; 7978edbede9SRichard Röjfors } 7988edbede9SRichard Röjfors 7998edbede9SRichard Röjfors /* only version 0 and 3 have the iNand routed to SDHCI */ 8008edbede9SRichard Röjfors if (((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER0) || 8018edbede9SRichard Röjfors ((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) { 8028edbede9SRichard Röjfors err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2, 8038edbede9SRichard Röjfors ARRAY_SIZE(timberdale_cells_bar2), 8040848c94fSMark Brown &dev->resource[2], msix_entries[0].vector, NULL); 8058edbede9SRichard Röjfors if (err) { 8068edbede9SRichard Röjfors dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); 8078edbede9SRichard Röjfors goto err_mfd2; 8088edbede9SRichard Röjfors } 8098edbede9SRichard Röjfors } 8108edbede9SRichard Röjfors 8118edbede9SRichard Röjfors kfree(msix_entries); 8128edbede9SRichard Röjfors 8138edbede9SRichard Röjfors dev_info(&dev->dev, 8148edbede9SRichard Röjfors "Found Timberdale Card. Rev: %d.%d, HW config: 0x%02x\n", 8158edbede9SRichard Röjfors priv->fw.major, priv->fw.minor, priv->fw.config); 8168edbede9SRichard Röjfors 8178edbede9SRichard Röjfors return 0; 8188edbede9SRichard Röjfors 8198edbede9SRichard Röjfors err_mfd2: 8208edbede9SRichard Röjfors mfd_remove_devices(&dev->dev); 8218edbede9SRichard Röjfors err_mfd: 8228edbede9SRichard Röjfors device_remove_file(&dev->dev, &dev_attr_fw_ver); 8238edbede9SRichard Röjfors err_create_file: 8248edbede9SRichard Röjfors pci_disable_msix(dev); 8258edbede9SRichard Röjfors err_msix: 826981c65a9SJulia Lawall kfree(msix_entries); 827981c65a9SJulia Lawall err_config: 8288edbede9SRichard Röjfors iounmap(priv->ctl_membase); 8298edbede9SRichard Röjfors err_ioremap: 8308edbede9SRichard Röjfors release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE); 8318edbede9SRichard Röjfors err_start: 8328edbede9SRichard Röjfors pci_disable_device(dev); 8338edbede9SRichard Röjfors err_enable: 8348edbede9SRichard Röjfors kfree(priv); 8358edbede9SRichard Röjfors return -ENODEV; 8368edbede9SRichard Röjfors } 8378edbede9SRichard Röjfors 8384740f73fSBill Pemberton static void timb_remove(struct pci_dev *dev) 8398edbede9SRichard Röjfors { 8408edbede9SRichard Röjfors struct timberdale_device *priv = pci_get_drvdata(dev); 8418edbede9SRichard Röjfors 8428edbede9SRichard Röjfors mfd_remove_devices(&dev->dev); 8438edbede9SRichard Röjfors 8448edbede9SRichard Röjfors device_remove_file(&dev->dev, &dev_attr_fw_ver); 8458edbede9SRichard Röjfors 8468edbede9SRichard Röjfors iounmap(priv->ctl_membase); 8478edbede9SRichard Röjfors release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE); 8488edbede9SRichard Röjfors 8498edbede9SRichard Röjfors pci_disable_msix(dev); 8508edbede9SRichard Röjfors pci_disable_device(dev); 8518edbede9SRichard Röjfors kfree(priv); 8528edbede9SRichard Röjfors } 8538edbede9SRichard Röjfors 85436fcd06cSJingoo Han static const struct pci_device_id timberdale_pci_tbl[] = { 8558edbede9SRichard Röjfors { PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) }, 8568edbede9SRichard Röjfors { 0 } 8578edbede9SRichard Röjfors }; 8588edbede9SRichard Röjfors MODULE_DEVICE_TABLE(pci, timberdale_pci_tbl); 8598edbede9SRichard Röjfors 8608edbede9SRichard Röjfors static struct pci_driver timberdale_pci_driver = { 8618edbede9SRichard Röjfors .name = DRIVER_NAME, 8628edbede9SRichard Röjfors .id_table = timberdale_pci_tbl, 8638edbede9SRichard Röjfors .probe = timb_probe, 86484449216SBill Pemberton .remove = timb_remove, 8658edbede9SRichard Röjfors }; 8668edbede9SRichard Röjfors 8670afb00e3SSachin Kamat module_pci_driver(timberdale_pci_driver); 8688edbede9SRichard Röjfors 8698edbede9SRichard Röjfors MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); 8708edbede9SRichard Röjfors MODULE_VERSION(DRV_VERSION); 8718edbede9SRichard Röjfors MODULE_LICENSE("GPL v2"); 872