xref: /openbmc/linux/drivers/mfd/timberdale.c (revision 2d51f035)
182c29810SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28edbede9SRichard Röjfors /*
38edbede9SRichard Röjfors  * timberdale.c timberdale FPGA MFD driver
48edbede9SRichard Röjfors  * Copyright (c) 2009 Intel Corporation
58edbede9SRichard Röjfors  */
68edbede9SRichard Röjfors 
78edbede9SRichard Röjfors /* Supports:
88edbede9SRichard Röjfors  * Timberdale FPGA
98edbede9SRichard Röjfors  */
108edbede9SRichard Röjfors 
118edbede9SRichard Röjfors #include <linux/kernel.h>
128edbede9SRichard Röjfors #include <linux/module.h>
138edbede9SRichard Röjfors #include <linux/pci.h>
148edbede9SRichard Röjfors #include <linux/mfd/core.h>
155a0e3ad6STejun Heo #include <linux/slab.h>
168edbede9SRichard Röjfors 
178edbede9SRichard Röjfors #include <linux/timb_gpio.h>
188edbede9SRichard Röjfors 
198edbede9SRichard Röjfors #include <linux/i2c.h>
20985ecf00SWolfram Sang #include <linux/platform_data/i2c-ocores.h>
217072b75cSWolfram Sang #include <linux/platform_data/i2c-xiic.h>
228edbede9SRichard Röjfors 
238edbede9SRichard Röjfors #include <linux/spi/spi.h>
248edbede9SRichard Röjfors #include <linux/spi/xilinx_spi.h>
258edbede9SRichard Röjfors #include <linux/spi/max7301.h>
268edbede9SRichard Röjfors #include <linux/spi/mc33880.h>
278edbede9SRichard Röjfors 
288fd70815SWolfram Sang #include <linux/platform_data/tsc2007.h>
29eb4b0ec7SMauro Carvalho Chehab #include <linux/platform_data/media/timb_radio.h>
30eb4b0ec7SMauro Carvalho Chehab #include <linux/platform_data/media/timb_video.h>
31071193ffSRichard Röjfors 
32dc64f30fSRichard Röjfors #include <linux/timb_dma.h>
33dc64f30fSRichard Röjfors 
346901ffd9SRichard Röjfors #include <linux/ks8842.h>
356901ffd9SRichard Röjfors 
368edbede9SRichard Röjfors #include "timberdale.h"
378edbede9SRichard Röjfors 
388edbede9SRichard Röjfors #define DRIVER_NAME "timberdale"
398edbede9SRichard Röjfors 
408edbede9SRichard Röjfors struct timberdale_device {
418edbede9SRichard Röjfors 	resource_size_t		ctl_mapbase;
428edbede9SRichard Röjfors 	unsigned char __iomem   *ctl_membase;
438edbede9SRichard Röjfors 	struct {
448edbede9SRichard Röjfors 		u32 major;
458edbede9SRichard Röjfors 		u32 minor;
468edbede9SRichard Röjfors 		u32 config;
478edbede9SRichard Röjfors 	} fw;
488edbede9SRichard Röjfors };
498edbede9SRichard Röjfors 
508edbede9SRichard Röjfors /*--------------------------------------------------------------------------*/
518edbede9SRichard Röjfors 
528edbede9SRichard Röjfors static struct tsc2007_platform_data timberdale_tsc2007_platform_data = {
538edbede9SRichard Röjfors 	.model = 2003,
548edbede9SRichard Röjfors 	.x_plate_ohms = 100
558edbede9SRichard Röjfors };
568edbede9SRichard Röjfors 
578edbede9SRichard Röjfors static struct i2c_board_info timberdale_i2c_board_info[] = {
588edbede9SRichard Röjfors 	{
598edbede9SRichard Röjfors 		I2C_BOARD_INFO("tsc2007", 0x48),
608edbede9SRichard Röjfors 		.platform_data = &timberdale_tsc2007_platform_data,
618edbede9SRichard Röjfors 		.irq = IRQ_TIMBERDALE_TSC_INT
628edbede9SRichard Röjfors 	},
638edbede9SRichard Röjfors };
648edbede9SRichard Röjfors 
65a9e9ce4cSBill Pemberton static struct xiic_i2c_platform_data
66d84027bcSRichard Röjfors timberdale_xiic_platform_data = {
67d84027bcSRichard Röjfors 	.devices = timberdale_i2c_board_info,
68d84027bcSRichard Röjfors 	.num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
69d84027bcSRichard Röjfors };
70d84027bcSRichard Röjfors 
71a9e9ce4cSBill Pemberton static struct ocores_i2c_platform_data
728edbede9SRichard Röjfors timberdale_ocores_platform_data = {
73d739a464SJayachandran C 	.reg_shift = 2,
748edbede9SRichard Röjfors 	.clock_khz = 62500,
758edbede9SRichard Röjfors 	.devices = timberdale_i2c_board_info,
768edbede9SRichard Röjfors 	.num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
778edbede9SRichard Röjfors };
788edbede9SRichard Röjfors 
79a73e5df1SBill Pemberton static const struct resource timberdale_xiic_resources[] = {
80d84027bcSRichard Röjfors 	{
81d84027bcSRichard Röjfors 		.start	= XIICOFFSET,
82d84027bcSRichard Röjfors 		.end	= XIICEND,
83d84027bcSRichard Röjfors 		.flags	= IORESOURCE_MEM,
84d84027bcSRichard Röjfors 	},
85d84027bcSRichard Röjfors 	{
86d84027bcSRichard Röjfors 		.start	= IRQ_TIMBERDALE_I2C,
87d84027bcSRichard Röjfors 		.end	= IRQ_TIMBERDALE_I2C,
88d84027bcSRichard Röjfors 		.flags	= IORESOURCE_IRQ,
89d84027bcSRichard Röjfors 	},
90d84027bcSRichard Röjfors };
91d84027bcSRichard Röjfors 
92a73e5df1SBill Pemberton static const struct resource timberdale_ocores_resources[] = {
938edbede9SRichard Röjfors 	{
948edbede9SRichard Röjfors 		.start	= OCORESOFFSET,
958edbede9SRichard Röjfors 		.end	= OCORESEND,
968edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
978edbede9SRichard Röjfors 	},
988edbede9SRichard Röjfors 	{
998edbede9SRichard Röjfors 		.start 	= IRQ_TIMBERDALE_I2C,
1008edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_I2C,
1018edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
1028edbede9SRichard Röjfors 	},
1038edbede9SRichard Röjfors };
1048edbede9SRichard Röjfors 
1054eaf4157SSachin Kamat static const struct max7301_platform_data timberdale_max7301_platform_data = {
1068edbede9SRichard Röjfors 	.base = 200
1078edbede9SRichard Röjfors };
1088edbede9SRichard Röjfors 
1094eaf4157SSachin Kamat static const struct mc33880_platform_data timberdale_mc33880_platform_data = {
1108edbede9SRichard Röjfors 	.base = 100
1118edbede9SRichard Röjfors };
1128edbede9SRichard Röjfors 
1138edbede9SRichard Röjfors static struct spi_board_info timberdale_spi_16bit_board_info[] = {
1148edbede9SRichard Röjfors 	{
1158edbede9SRichard Röjfors 		.modalias = "max7301",
1168edbede9SRichard Röjfors 		.max_speed_hz = 26000,
1178edbede9SRichard Röjfors 		.chip_select = 2,
1188edbede9SRichard Röjfors 		.mode = SPI_MODE_0,
1198edbede9SRichard Röjfors 		.platform_data = &timberdale_max7301_platform_data
1208edbede9SRichard Röjfors 	},
1218edbede9SRichard Röjfors };
1228edbede9SRichard Röjfors 
1238edbede9SRichard Röjfors static struct spi_board_info timberdale_spi_8bit_board_info[] = {
1248edbede9SRichard Röjfors 	{
1258edbede9SRichard Röjfors 		.modalias = "mc33880",
1268edbede9SRichard Röjfors 		.max_speed_hz = 4000,
1278edbede9SRichard Röjfors 		.chip_select = 1,
1288edbede9SRichard Röjfors 		.mode = SPI_MODE_1,
1298edbede9SRichard Röjfors 		.platform_data = &timberdale_mc33880_platform_data
1308edbede9SRichard Röjfors 	},
1318edbede9SRichard Röjfors };
1328edbede9SRichard Röjfors 
133a9e9ce4cSBill Pemberton static struct xspi_platform_data timberdale_xspi_platform_data = {
1348edbede9SRichard Röjfors 	.num_chipselect = 3,
1358edbede9SRichard Röjfors 	/* bits per word and devices will be filled in runtime depending
1368edbede9SRichard Röjfors 	 * on the HW config
1378edbede9SRichard Röjfors 	 */
1388edbede9SRichard Röjfors };
1398edbede9SRichard Röjfors 
140a73e5df1SBill Pemberton static const struct resource timberdale_spi_resources[] = {
1418edbede9SRichard Röjfors 	{
1428edbede9SRichard Röjfors 		.start 	= SPIOFFSET,
1438edbede9SRichard Röjfors 		.end	= SPIEND,
1448edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
1458edbede9SRichard Röjfors 	},
1468edbede9SRichard Röjfors 	{
1478edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_SPI,
1488edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_SPI,
1498edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
1508edbede9SRichard Röjfors 	},
1518edbede9SRichard Röjfors };
1528edbede9SRichard Röjfors 
153a9e9ce4cSBill Pemberton static struct ks8842_platform_data
1546901ffd9SRichard Röjfors 	timberdale_ks8842_platform_data = {
1556901ffd9SRichard Röjfors 	.rx_dma_channel = DMA_ETH_RX,
1566901ffd9SRichard Röjfors 	.tx_dma_channel = DMA_ETH_TX
1576901ffd9SRichard Röjfors };
1586901ffd9SRichard Röjfors 
159a73e5df1SBill Pemberton static const struct resource timberdale_eth_resources[] = {
1608edbede9SRichard Röjfors 	{
1618edbede9SRichard Röjfors 		.start	= ETHOFFSET,
1628edbede9SRichard Röjfors 		.end	= ETHEND,
1638edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
1648edbede9SRichard Röjfors 	},
1658edbede9SRichard Röjfors 	{
1668edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_ETHSW_IF,
1678edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_ETHSW_IF,
1688edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
1698edbede9SRichard Röjfors 	},
1708edbede9SRichard Röjfors };
1718edbede9SRichard Röjfors 
172a9e9ce4cSBill Pemberton static struct timbgpio_platform_data
1738edbede9SRichard Röjfors 	timberdale_gpio_platform_data = {
1748edbede9SRichard Röjfors 	.gpio_base = 0,
1758edbede9SRichard Röjfors 	.nr_pins = GPIO_NR_PINS,
1768edbede9SRichard Röjfors 	.irq_base = 200,
1778edbede9SRichard Röjfors };
1788edbede9SRichard Röjfors 
179a73e5df1SBill Pemberton static const struct resource timberdale_gpio_resources[] = {
1808edbede9SRichard Röjfors 	{
1818edbede9SRichard Röjfors 		.start	= GPIOOFFSET,
1828edbede9SRichard Röjfors 		.end	= GPIOEND,
1838edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
1848edbede9SRichard Röjfors 	},
1858edbede9SRichard Röjfors 	{
1868edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_GPIO,
1878edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_GPIO,
1888edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
1898edbede9SRichard Röjfors 	},
1908edbede9SRichard Röjfors };
1918edbede9SRichard Röjfors 
192a73e5df1SBill Pemberton static const struct resource timberdale_mlogicore_resources[] = {
1938edbede9SRichard Röjfors 	{
1948edbede9SRichard Röjfors 		.start	= MLCOREOFFSET,
1958edbede9SRichard Röjfors 		.end	= MLCOREEND,
1968edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
1978edbede9SRichard Röjfors 	},
1988edbede9SRichard Röjfors 	{
1998edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_MLCORE,
2008edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_MLCORE,
2018edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
2028edbede9SRichard Röjfors 	},
2038edbede9SRichard Röjfors 	{
2048edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_MLCORE_BUF,
2058edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_MLCORE_BUF,
2068edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
2078edbede9SRichard Röjfors 	},
2088edbede9SRichard Röjfors };
2098edbede9SRichard Röjfors 
210a73e5df1SBill Pemberton static const struct resource timberdale_uart_resources[] = {
2118edbede9SRichard Röjfors 	{
2128edbede9SRichard Röjfors 		.start	= UARTOFFSET,
2138edbede9SRichard Röjfors 		.end	= UARTEND,
2148edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
2158edbede9SRichard Röjfors 	},
2168edbede9SRichard Röjfors 	{
2178edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_UART,
2188edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_UART,
2198edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
2208edbede9SRichard Röjfors 	},
2218edbede9SRichard Röjfors };
2228edbede9SRichard Röjfors 
223a73e5df1SBill Pemberton static const struct resource timberdale_uartlite_resources[] = {
2248edbede9SRichard Röjfors 	{
2258edbede9SRichard Röjfors 		.start	= UARTLITEOFFSET,
2268edbede9SRichard Röjfors 		.end	= UARTLITEEND,
2278edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
2288edbede9SRichard Röjfors 	},
2298edbede9SRichard Röjfors 	{
2308edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_UARTLITE,
2318edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_UARTLITE,
2328edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
2338edbede9SRichard Röjfors 	},
2348edbede9SRichard Röjfors };
2358edbede9SRichard Röjfors 
236a9e9ce4cSBill Pemberton static struct i2c_board_info timberdale_adv7180_i2c_board_info = {
237c091575cSRichard Röjfors 	/* Requires jumper JP9 to be off */
238c091575cSRichard Röjfors 	I2C_BOARD_INFO("adv7180", 0x42 >> 1),
239c091575cSRichard Röjfors 	.irq = IRQ_TIMBERDALE_ADV7180
240c091575cSRichard Röjfors };
241c091575cSRichard Röjfors 
242a9e9ce4cSBill Pemberton static struct timb_video_platform_data
243c091575cSRichard Röjfors 	timberdale_video_platform_data = {
244c091575cSRichard Röjfors 	.dma_channel = DMA_VIDEO_RX,
245c091575cSRichard Röjfors 	.i2c_adapter = 0,
246c091575cSRichard Röjfors 	.encoder = {
247c091575cSRichard Röjfors 		.info = &timberdale_adv7180_i2c_board_info
248c091575cSRichard Röjfors 	}
249c091575cSRichard Röjfors };
250c091575cSRichard Röjfors 
251a73e5df1SBill Pemberton static const struct resource
252c091575cSRichard Röjfors timberdale_radio_resources[] = {
253071193ffSRichard Röjfors 	{
254071193ffSRichard Röjfors 		.start	= RDSOFFSET,
255071193ffSRichard Röjfors 		.end	= RDSEND,
256071193ffSRichard Röjfors 		.flags	= IORESOURCE_MEM,
257071193ffSRichard Röjfors 	},
258071193ffSRichard Röjfors 	{
259071193ffSRichard Röjfors 		.start	= IRQ_TIMBERDALE_RDS,
260071193ffSRichard Röjfors 		.end	= IRQ_TIMBERDALE_RDS,
261071193ffSRichard Röjfors 		.flags	= IORESOURCE_IRQ,
262071193ffSRichard Röjfors 	},
263071193ffSRichard Röjfors };
264071193ffSRichard Röjfors 
265a9e9ce4cSBill Pemberton static struct i2c_board_info timberdale_tef6868_i2c_board_info = {
266071193ffSRichard Röjfors 	I2C_BOARD_INFO("tef6862", 0x60)
267071193ffSRichard Röjfors };
268071193ffSRichard Röjfors 
269a9e9ce4cSBill Pemberton static struct i2c_board_info timberdale_saa7706_i2c_board_info = {
270071193ffSRichard Röjfors 	I2C_BOARD_INFO("saa7706h", 0x1C)
271071193ffSRichard Röjfors };
272071193ffSRichard Röjfors 
273a9e9ce4cSBill Pemberton static struct timb_radio_platform_data
274071193ffSRichard Röjfors 	timberdale_radio_platform_data = {
275071193ffSRichard Röjfors 	.i2c_adapter = 0,
2769cd49719SRichard Röjfors 	.tuner = &timberdale_tef6868_i2c_board_info,
2779cd49719SRichard Röjfors 	.dsp = &timberdale_saa7706_i2c_board_info
278071193ffSRichard Röjfors };
279071193ffSRichard Röjfors 
280a73e5df1SBill Pemberton static const struct resource timberdale_video_resources[] = {
281c091575cSRichard Röjfors 	{
282c091575cSRichard Röjfors 		.start	= LOGIWOFFSET,
283c091575cSRichard Röjfors 		.end	= LOGIWEND,
284c091575cSRichard Röjfors 		.flags	= IORESOURCE_MEM,
285c091575cSRichard Röjfors 	},
286c091575cSRichard Röjfors 	/*
287c091575cSRichard Röjfors 	note that the "frame buffer" is located in DMA area
288c091575cSRichard Röjfors 	starting at 0x1200000
289c091575cSRichard Röjfors 	*/
290c091575cSRichard Röjfors };
291c091575cSRichard Röjfors 
292a9e9ce4cSBill Pemberton static struct timb_dma_platform_data timb_dma_platform_data = {
293dc64f30fSRichard Röjfors 	.nr_channels = 10,
294dc64f30fSRichard Röjfors 	.channels = {
295dc64f30fSRichard Röjfors 		{
296dc64f30fSRichard Röjfors 			/* UART RX */
297dc64f30fSRichard Röjfors 			.rx = true,
298dc64f30fSRichard Röjfors 			.descriptors = 2,
299dc64f30fSRichard Röjfors 			.descriptor_elements = 1
300dc64f30fSRichard Röjfors 		},
301dc64f30fSRichard Röjfors 		{
302dc64f30fSRichard Röjfors 			/* UART TX */
303dc64f30fSRichard Röjfors 			.rx = false,
304dc64f30fSRichard Röjfors 			.descriptors = 2,
305dc64f30fSRichard Röjfors 			.descriptor_elements = 1
306dc64f30fSRichard Röjfors 		},
307dc64f30fSRichard Röjfors 		{
308dc64f30fSRichard Röjfors 			/* MLB RX */
309dc64f30fSRichard Röjfors 			.rx = true,
310dc64f30fSRichard Röjfors 			.descriptors = 2,
311dc64f30fSRichard Röjfors 			.descriptor_elements = 1
312dc64f30fSRichard Röjfors 		},
313dc64f30fSRichard Röjfors 		{
314dc64f30fSRichard Röjfors 			/* MLB TX */
315dc64f30fSRichard Röjfors 			.rx = false,
316dc64f30fSRichard Röjfors 			.descriptors = 2,
317dc64f30fSRichard Röjfors 			.descriptor_elements = 1
318dc64f30fSRichard Röjfors 		},
319dc64f30fSRichard Röjfors 		{
320dc64f30fSRichard Röjfors 			/* Video RX */
321dc64f30fSRichard Röjfors 			.rx = true,
322dc64f30fSRichard Röjfors 			.bytes_per_line = 1440,
323dc64f30fSRichard Röjfors 			.descriptors = 2,
324dc64f30fSRichard Röjfors 			.descriptor_elements = 16
325dc64f30fSRichard Röjfors 		},
326dc64f30fSRichard Röjfors 		{
327dc64f30fSRichard Röjfors 			/* Video framedrop */
328dc64f30fSRichard Röjfors 		},
329dc64f30fSRichard Röjfors 		{
330dc64f30fSRichard Röjfors 			/* SDHCI RX */
331dc64f30fSRichard Röjfors 			.rx = true,
332dc64f30fSRichard Röjfors 		},
333dc64f30fSRichard Röjfors 		{
334dc64f30fSRichard Röjfors 			/* SDHCI TX */
335dc64f30fSRichard Röjfors 		},
336dc64f30fSRichard Röjfors 		{
337dc64f30fSRichard Röjfors 			/* ETH RX */
338dc64f30fSRichard Röjfors 			.rx = true,
339dc64f30fSRichard Röjfors 			.descriptors = 2,
340dc64f30fSRichard Röjfors 			.descriptor_elements = 1
341dc64f30fSRichard Röjfors 		},
342dc64f30fSRichard Röjfors 		{
343dc64f30fSRichard Röjfors 			/* ETH TX */
344dc64f30fSRichard Röjfors 			.rx = false,
345dc64f30fSRichard Röjfors 			.descriptors = 2,
346dc64f30fSRichard Röjfors 			.descriptor_elements = 1
347dc64f30fSRichard Röjfors 		},
348dc64f30fSRichard Röjfors 	}
349dc64f30fSRichard Röjfors };
350dc64f30fSRichard Röjfors 
351a73e5df1SBill Pemberton static const struct resource timberdale_dma_resources[] = {
3528edbede9SRichard Röjfors 	{
3538edbede9SRichard Röjfors 		.start	= DMAOFFSET,
3548edbede9SRichard Röjfors 		.end	= DMAEND,
3558edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
3568edbede9SRichard Röjfors 	},
3578edbede9SRichard Röjfors 	{
3588edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_DMA,
3598edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_DMA,
3608edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
3618edbede9SRichard Röjfors 	},
3628edbede9SRichard Röjfors };
3638edbede9SRichard Röjfors 
3645ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar0_cfg0[] = {
3658edbede9SRichard Röjfors 	{
366dc64f30fSRichard Röjfors 		.name = "timb-dma",
367dc64f30fSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
368dc64f30fSRichard Röjfors 		.resources = timberdale_dma_resources,
3693271d382SSamuel Ortiz 		.platform_data = &timb_dma_platform_data,
3703271d382SSamuel Ortiz 		.pdata_size = sizeof(timb_dma_platform_data),
371dc64f30fSRichard Röjfors 	},
372dc64f30fSRichard Röjfors 	{
3738edbede9SRichard Röjfors 		.name = "timb-uart",
3748edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_uart_resources),
3758edbede9SRichard Röjfors 		.resources = timberdale_uart_resources,
3768edbede9SRichard Röjfors 	},
3778edbede9SRichard Röjfors 	{
378d84027bcSRichard Röjfors 		.name = "xiic-i2c",
379d84027bcSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
380d84027bcSRichard Röjfors 		.resources = timberdale_xiic_resources,
3813271d382SSamuel Ortiz 		.platform_data = &timberdale_xiic_platform_data,
3823271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_xiic_platform_data),
383d84027bcSRichard Röjfors 	},
384d84027bcSRichard Röjfors 	{
3858edbede9SRichard Röjfors 		.name = "timb-gpio",
3868edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
3878edbede9SRichard Röjfors 		.resources = timberdale_gpio_resources,
3883271d382SSamuel Ortiz 		.platform_data = &timberdale_gpio_platform_data,
3893271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_gpio_platform_data),
3908edbede9SRichard Röjfors 	},
3918edbede9SRichard Röjfors 	{
392c091575cSRichard Röjfors 		.name = "timb-video",
393c091575cSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_video_resources),
394c091575cSRichard Röjfors 		.resources = timberdale_video_resources,
3953271d382SSamuel Ortiz 		.platform_data = &timberdale_video_platform_data,
3963271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_video_platform_data),
397c091575cSRichard Röjfors 	},
398c091575cSRichard Röjfors 	{
399071193ffSRichard Röjfors 		.name = "timb-radio",
400071193ffSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
401071193ffSRichard Röjfors 		.resources = timberdale_radio_resources,
4023271d382SSamuel Ortiz 		.platform_data = &timberdale_radio_platform_data,
4033271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_radio_platform_data),
404071193ffSRichard Röjfors 	},
405071193ffSRichard Röjfors 	{
4068edbede9SRichard Röjfors 		.name = "xilinx_spi",
4078edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_spi_resources),
4088edbede9SRichard Röjfors 		.resources = timberdale_spi_resources,
4093271d382SSamuel Ortiz 		.platform_data = &timberdale_xspi_platform_data,
4103271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_xspi_platform_data),
4118edbede9SRichard Röjfors 	},
4128edbede9SRichard Röjfors 	{
4138edbede9SRichard Röjfors 		.name = "ks8842",
4148edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_eth_resources),
4158edbede9SRichard Röjfors 		.resources = timberdale_eth_resources,
4163271d382SSamuel Ortiz 		.platform_data = &timberdale_ks8842_platform_data,
4173271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_ks8842_platform_data),
4188edbede9SRichard Röjfors 	},
419dc64f30fSRichard Röjfors };
420dc64f30fSRichard Röjfors 
4215ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar0_cfg1[] = {
4228edbede9SRichard Röjfors 	{
4238edbede9SRichard Röjfors 		.name = "timb-dma",
4248edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
4258edbede9SRichard Röjfors 		.resources = timberdale_dma_resources,
4263271d382SSamuel Ortiz 		.platform_data = &timb_dma_platform_data,
4273271d382SSamuel Ortiz 		.pdata_size = sizeof(timb_dma_platform_data),
4288edbede9SRichard Röjfors 	},
4298edbede9SRichard Röjfors 	{
4308edbede9SRichard Röjfors 		.name = "timb-uart",
4318edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_uart_resources),
4328edbede9SRichard Röjfors 		.resources = timberdale_uart_resources,
4338edbede9SRichard Röjfors 	},
4348edbede9SRichard Röjfors 	{
4358edbede9SRichard Röjfors 		.name = "uartlite",
4368edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_uartlite_resources),
4378edbede9SRichard Röjfors 		.resources = timberdale_uartlite_resources,
4388edbede9SRichard Röjfors 	},
4398edbede9SRichard Röjfors 	{
440d84027bcSRichard Röjfors 		.name = "xiic-i2c",
441d84027bcSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
442d84027bcSRichard Röjfors 		.resources = timberdale_xiic_resources,
4433271d382SSamuel Ortiz 		.platform_data = &timberdale_xiic_platform_data,
4443271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_xiic_platform_data),
445d84027bcSRichard Röjfors 	},
446d84027bcSRichard Röjfors 	{
4478edbede9SRichard Röjfors 		.name = "timb-gpio",
4488edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
4498edbede9SRichard Röjfors 		.resources = timberdale_gpio_resources,
4503271d382SSamuel Ortiz 		.platform_data = &timberdale_gpio_platform_data,
4513271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_gpio_platform_data),
4528edbede9SRichard Röjfors 	},
4538edbede9SRichard Röjfors 	{
4548edbede9SRichard Röjfors 		.name = "timb-mlogicore",
4558edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_mlogicore_resources),
4568edbede9SRichard Röjfors 		.resources = timberdale_mlogicore_resources,
4578edbede9SRichard Röjfors 	},
4588edbede9SRichard Röjfors 	{
459c091575cSRichard Röjfors 		.name = "timb-video",
460c091575cSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_video_resources),
461c091575cSRichard Röjfors 		.resources = timberdale_video_resources,
4623271d382SSamuel Ortiz 		.platform_data = &timberdale_video_platform_data,
4633271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_video_platform_data),
464c091575cSRichard Röjfors 	},
465c091575cSRichard Röjfors 	{
466071193ffSRichard Röjfors 		.name = "timb-radio",
467071193ffSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
468071193ffSRichard Röjfors 		.resources = timberdale_radio_resources,
4693271d382SSamuel Ortiz 		.platform_data = &timberdale_radio_platform_data,
4703271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_radio_platform_data),
471071193ffSRichard Röjfors 	},
472071193ffSRichard Röjfors 	{
4738edbede9SRichard Röjfors 		.name = "xilinx_spi",
4748edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_spi_resources),
4758edbede9SRichard Röjfors 		.resources = timberdale_spi_resources,
4763271d382SSamuel Ortiz 		.platform_data = &timberdale_xspi_platform_data,
4773271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_xspi_platform_data),
4788edbede9SRichard Röjfors 	},
4798edbede9SRichard Röjfors 	{
4808edbede9SRichard Röjfors 		.name = "ks8842",
4818edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_eth_resources),
4828edbede9SRichard Röjfors 		.resources = timberdale_eth_resources,
4833271d382SSamuel Ortiz 		.platform_data = &timberdale_ks8842_platform_data,
4843271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_ks8842_platform_data),
4858edbede9SRichard Röjfors 	},
486dc64f30fSRichard Röjfors };
487dc64f30fSRichard Röjfors 
4885ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar0_cfg2[] = {
4898edbede9SRichard Röjfors 	{
4908edbede9SRichard Röjfors 		.name = "timb-dma",
4918edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
4928edbede9SRichard Röjfors 		.resources = timberdale_dma_resources,
4933271d382SSamuel Ortiz 		.platform_data = &timb_dma_platform_data,
4943271d382SSamuel Ortiz 		.pdata_size = sizeof(timb_dma_platform_data),
4958edbede9SRichard Röjfors 	},
4968edbede9SRichard Röjfors 	{
4978edbede9SRichard Röjfors 		.name = "timb-uart",
4988edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_uart_resources),
4998edbede9SRichard Röjfors 		.resources = timberdale_uart_resources,
5008edbede9SRichard Röjfors 	},
5018edbede9SRichard Röjfors 	{
502d84027bcSRichard Röjfors 		.name = "xiic-i2c",
503d84027bcSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
504d84027bcSRichard Röjfors 		.resources = timberdale_xiic_resources,
5053271d382SSamuel Ortiz 		.platform_data = &timberdale_xiic_platform_data,
5063271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_xiic_platform_data),
507d84027bcSRichard Röjfors 	},
508d84027bcSRichard Röjfors 	{
5098edbede9SRichard Röjfors 		.name = "timb-gpio",
5108edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
5118edbede9SRichard Röjfors 		.resources = timberdale_gpio_resources,
5123271d382SSamuel Ortiz 		.platform_data = &timberdale_gpio_platform_data,
5133271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_gpio_platform_data),
5148edbede9SRichard Röjfors 	},
5158edbede9SRichard Röjfors 	{
516c091575cSRichard Röjfors 		.name = "timb-video",
517c091575cSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_video_resources),
518c091575cSRichard Röjfors 		.resources = timberdale_video_resources,
5193271d382SSamuel Ortiz 		.platform_data = &timberdale_video_platform_data,
5203271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_video_platform_data),
521c091575cSRichard Röjfors 	},
522c091575cSRichard Röjfors 	{
523071193ffSRichard Röjfors 		.name = "timb-radio",
524071193ffSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
525071193ffSRichard Röjfors 		.resources = timberdale_radio_resources,
5263271d382SSamuel Ortiz 		.platform_data = &timberdale_radio_platform_data,
5273271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_radio_platform_data),
528071193ffSRichard Röjfors 	},
529071193ffSRichard Röjfors 	{
5308edbede9SRichard Röjfors 		.name = "xilinx_spi",
5318edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_spi_resources),
5328edbede9SRichard Röjfors 		.resources = timberdale_spi_resources,
5333271d382SSamuel Ortiz 		.platform_data = &timberdale_xspi_platform_data,
5343271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_xspi_platform_data),
5358edbede9SRichard Röjfors 	},
536dc64f30fSRichard Röjfors };
537dc64f30fSRichard Röjfors 
5385ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar0_cfg3[] = {
5398edbede9SRichard Röjfors 	{
5408edbede9SRichard Röjfors 		.name = "timb-dma",
5418edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
5428edbede9SRichard Röjfors 		.resources = timberdale_dma_resources,
5433271d382SSamuel Ortiz 		.platform_data = &timb_dma_platform_data,
5443271d382SSamuel Ortiz 		.pdata_size = sizeof(timb_dma_platform_data),
5458edbede9SRichard Röjfors 	},
5468edbede9SRichard Röjfors 	{
5478edbede9SRichard Röjfors 		.name = "timb-uart",
5488edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_uart_resources),
5498edbede9SRichard Röjfors 		.resources = timberdale_uart_resources,
5508edbede9SRichard Röjfors 	},
5518edbede9SRichard Röjfors 	{
5528edbede9SRichard Röjfors 		.name = "ocores-i2c",
5538edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_ocores_resources),
5548edbede9SRichard Röjfors 		.resources = timberdale_ocores_resources,
5553271d382SSamuel Ortiz 		.platform_data = &timberdale_ocores_platform_data,
5563271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_ocores_platform_data),
5578edbede9SRichard Röjfors 	},
5588edbede9SRichard Röjfors 	{
5598edbede9SRichard Röjfors 		.name = "timb-gpio",
5608edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
5618edbede9SRichard Röjfors 		.resources = timberdale_gpio_resources,
5623271d382SSamuel Ortiz 		.platform_data = &timberdale_gpio_platform_data,
5633271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_gpio_platform_data),
5648edbede9SRichard Röjfors 	},
5658edbede9SRichard Röjfors 	{
566c091575cSRichard Röjfors 		.name = "timb-video",
567c091575cSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_video_resources),
568c091575cSRichard Röjfors 		.resources = timberdale_video_resources,
5693271d382SSamuel Ortiz 		.platform_data = &timberdale_video_platform_data,
5703271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_video_platform_data),
571c091575cSRichard Röjfors 	},
572c091575cSRichard Röjfors 	{
573071193ffSRichard Röjfors 		.name = "timb-radio",
574071193ffSRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
575071193ffSRichard Röjfors 		.resources = timberdale_radio_resources,
5763271d382SSamuel Ortiz 		.platform_data = &timberdale_radio_platform_data,
5773271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_radio_platform_data),
578071193ffSRichard Röjfors 	},
579071193ffSRichard Röjfors 	{
5808edbede9SRichard Röjfors 		.name = "xilinx_spi",
5818edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_spi_resources),
5828edbede9SRichard Röjfors 		.resources = timberdale_spi_resources,
5833271d382SSamuel Ortiz 		.platform_data = &timberdale_xspi_platform_data,
5843271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_xspi_platform_data),
5858edbede9SRichard Röjfors 	},
5868edbede9SRichard Röjfors 	{
5878edbede9SRichard Röjfors 		.name = "ks8842",
5888edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_eth_resources),
5898edbede9SRichard Röjfors 		.resources = timberdale_eth_resources,
5903271d382SSamuel Ortiz 		.platform_data = &timberdale_ks8842_platform_data,
5913271d382SSamuel Ortiz 		.pdata_size = sizeof(timberdale_ks8842_platform_data),
5928edbede9SRichard Röjfors 	},
5938edbede9SRichard Röjfors };
5948edbede9SRichard Röjfors 
595a73e5df1SBill Pemberton static const struct resource timberdale_sdhc_resources[] = {
5968edbede9SRichard Röjfors 	/* located in bar 1 and bar 2 */
5978edbede9SRichard Röjfors 	{
5988edbede9SRichard Röjfors 		.start	= SDHC0OFFSET,
5998edbede9SRichard Röjfors 		.end	= SDHC0END,
6008edbede9SRichard Röjfors 		.flags	= IORESOURCE_MEM,
6018edbede9SRichard Röjfors 	},
6028edbede9SRichard Röjfors 	{
6038edbede9SRichard Röjfors 		.start	= IRQ_TIMBERDALE_SDHC,
6048edbede9SRichard Röjfors 		.end	= IRQ_TIMBERDALE_SDHC,
6058edbede9SRichard Röjfors 		.flags	= IORESOURCE_IRQ,
6068edbede9SRichard Röjfors 	},
6078edbede9SRichard Röjfors };
6088edbede9SRichard Röjfors 
6095ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar1[] = {
6108edbede9SRichard Röjfors 	{
6118edbede9SRichard Röjfors 		.name = "sdhci",
6128edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
6138edbede9SRichard Röjfors 		.resources = timberdale_sdhc_resources,
6148edbede9SRichard Röjfors 	},
6158edbede9SRichard Röjfors };
6168edbede9SRichard Röjfors 
6175ac98553SGeert Uytterhoeven static const struct mfd_cell timberdale_cells_bar2[] = {
6188edbede9SRichard Röjfors 	{
6198edbede9SRichard Röjfors 		.name = "sdhci",
6208edbede9SRichard Röjfors 		.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
6218edbede9SRichard Röjfors 		.resources = timberdale_sdhc_resources,
6228edbede9SRichard Röjfors 	},
6238edbede9SRichard Röjfors };
6248edbede9SRichard Röjfors 
fw_ver_show(struct device * dev,struct device_attribute * attr,char * buf)625*ae7955f7SZhen Lei static ssize_t fw_ver_show(struct device *dev,
626*ae7955f7SZhen Lei 			   struct device_attribute *attr, char *buf)
6278edbede9SRichard Röjfors {
628aee36174SChuhong Yuan 	struct timberdale_device *priv = dev_get_drvdata(dev);
6298edbede9SRichard Röjfors 
6308edbede9SRichard Röjfors 	return sprintf(buf, "%d.%d.%d\n", priv->fw.major, priv->fw.minor,
6318edbede9SRichard Röjfors 		priv->fw.config);
6328edbede9SRichard Röjfors }
6338edbede9SRichard Röjfors 
634*ae7955f7SZhen Lei static DEVICE_ATTR_RO(fw_ver);
6358edbede9SRichard Röjfors 
6368edbede9SRichard Röjfors /*--------------------------------------------------------------------------*/
6378edbede9SRichard Röjfors 
timb_probe(struct pci_dev * dev,const struct pci_device_id * id)638f791be49SBill Pemberton static int timb_probe(struct pci_dev *dev,
6398edbede9SRichard Röjfors 	const struct pci_device_id *id)
6408edbede9SRichard Röjfors {
6418edbede9SRichard Röjfors 	struct timberdale_device *priv;
6428edbede9SRichard Röjfors 	int err, i;
6438edbede9SRichard Röjfors 	resource_size_t mapbase;
6448edbede9SRichard Röjfors 	struct msix_entry *msix_entries = NULL;
6458edbede9SRichard Röjfors 	u8 ip_setup;
6468edbede9SRichard Röjfors 
6478edbede9SRichard Röjfors 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
6488edbede9SRichard Röjfors 	if (!priv)
6498edbede9SRichard Röjfors 		return -ENOMEM;
6508edbede9SRichard Röjfors 
6518edbede9SRichard Röjfors 	pci_set_drvdata(dev, priv);
6528edbede9SRichard Röjfors 
6538edbede9SRichard Röjfors 	err = pci_enable_device(dev);
6548edbede9SRichard Röjfors 	if (err)
6558edbede9SRichard Röjfors 		goto err_enable;
6568edbede9SRichard Röjfors 
6578edbede9SRichard Röjfors 	mapbase = pci_resource_start(dev, 0);
6588edbede9SRichard Röjfors 	if (!mapbase) {
6598edbede9SRichard Röjfors 		dev_err(&dev->dev, "No resource\n");
6608edbede9SRichard Röjfors 		goto err_start;
6618edbede9SRichard Röjfors 	}
6628edbede9SRichard Röjfors 
6638edbede9SRichard Röjfors 	/* create a resource for the PCI master register */
6648edbede9SRichard Röjfors 	priv->ctl_mapbase = mapbase + CHIPCTLOFFSET;
6658edbede9SRichard Röjfors 	if (!request_mem_region(priv->ctl_mapbase, CHIPCTLSIZE, "timb-ctl")) {
6668edbede9SRichard Röjfors 		dev_err(&dev->dev, "Failed to request ctl mem\n");
6677902fe8cSJingoo Han 		goto err_start;
6688edbede9SRichard Röjfors 	}
6698edbede9SRichard Röjfors 
6708edbede9SRichard Röjfors 	priv->ctl_membase = ioremap(priv->ctl_mapbase, CHIPCTLSIZE);
6718edbede9SRichard Röjfors 	if (!priv->ctl_membase) {
6728edbede9SRichard Röjfors 		dev_err(&dev->dev, "ioremap failed for ctl mem\n");
6738edbede9SRichard Röjfors 		goto err_ioremap;
6748edbede9SRichard Röjfors 	}
6758edbede9SRichard Röjfors 
6768edbede9SRichard Röjfors 	/* read the HW config */
6778edbede9SRichard Röjfors 	priv->fw.major = ioread32(priv->ctl_membase + TIMB_REV_MAJOR);
6788edbede9SRichard Röjfors 	priv->fw.minor = ioread32(priv->ctl_membase + TIMB_REV_MINOR);
6798edbede9SRichard Röjfors 	priv->fw.config = ioread32(priv->ctl_membase + TIMB_HW_CONFIG);
6808edbede9SRichard Röjfors 
6818edbede9SRichard Röjfors 	if (priv->fw.major > TIMB_SUPPORTED_MAJOR) {
6828edbede9SRichard Röjfors 		dev_err(&dev->dev, "The driver supports an older "
6838edbede9SRichard Röjfors 			"version of the FPGA, please update the driver to "
6848edbede9SRichard Röjfors 			"support %d.%d\n", priv->fw.major, priv->fw.minor);
685981c65a9SJulia Lawall 		goto err_config;
6868edbede9SRichard Röjfors 	}
6878edbede9SRichard Röjfors 	if (priv->fw.major < TIMB_SUPPORTED_MAJOR ||
6888edbede9SRichard Röjfors 		priv->fw.minor < TIMB_REQUIRED_MINOR) {
6898edbede9SRichard Röjfors 		dev_err(&dev->dev, "The FPGA image is too old (%d.%d), "
6908edbede9SRichard Röjfors 			"please upgrade the FPGA to at least: %d.%d\n",
6918edbede9SRichard Röjfors 			priv->fw.major, priv->fw.minor,
6928edbede9SRichard Röjfors 			TIMB_SUPPORTED_MAJOR, TIMB_REQUIRED_MINOR);
693981c65a9SJulia Lawall 		goto err_config;
6948edbede9SRichard Röjfors 	}
6958edbede9SRichard Röjfors 
6966396bb22SKees Cook 	msix_entries = kcalloc(TIMBERDALE_NR_IRQS, sizeof(*msix_entries),
6978edbede9SRichard Röjfors 			       GFP_KERNEL);
6988edbede9SRichard Röjfors 	if (!msix_entries)
699981c65a9SJulia Lawall 		goto err_config;
7008edbede9SRichard Röjfors 
7018edbede9SRichard Röjfors 	for (i = 0; i < TIMBERDALE_NR_IRQS; i++)
7028edbede9SRichard Röjfors 		msix_entries[i].entry = i;
7038edbede9SRichard Röjfors 
704471212d9SAlexander Gordeev 	err = pci_enable_msix_exact(dev, msix_entries, TIMBERDALE_NR_IRQS);
7058edbede9SRichard Röjfors 	if (err) {
7068edbede9SRichard Röjfors 		dev_err(&dev->dev,
7078edbede9SRichard Röjfors 			"MSI-X init failed: %d, expected entries: %d\n",
7088edbede9SRichard Röjfors 			err, TIMBERDALE_NR_IRQS);
7098edbede9SRichard Röjfors 		goto err_msix;
7108edbede9SRichard Röjfors 	}
7118edbede9SRichard Röjfors 
7128edbede9SRichard Röjfors 	err = device_create_file(&dev->dev, &dev_attr_fw_ver);
7138edbede9SRichard Röjfors 	if (err)
7148edbede9SRichard Röjfors 		goto err_create_file;
7158edbede9SRichard Röjfors 
7168edbede9SRichard Röjfors 	/* Reset all FPGA PLB peripherals */
7178edbede9SRichard Röjfors 	iowrite32(0x1, priv->ctl_membase + TIMB_SW_RST);
7188edbede9SRichard Röjfors 
7198edbede9SRichard Röjfors 	/* update IRQ offsets in I2C board info */
7208edbede9SRichard Röjfors 	for (i = 0; i < ARRAY_SIZE(timberdale_i2c_board_info); i++)
7218edbede9SRichard Röjfors 		timberdale_i2c_board_info[i].irq =
7228edbede9SRichard Röjfors 			msix_entries[timberdale_i2c_board_info[i].irq].vector;
7238edbede9SRichard Röjfors 
7248edbede9SRichard Röjfors 	/* Update the SPI configuration depending on the HW (8 or 16 bit) */
7258edbede9SRichard Röjfors 	if (priv->fw.config & TIMB_HW_CONFIG_SPI_8BIT) {
7268edbede9SRichard Röjfors 		timberdale_xspi_platform_data.bits_per_word = 8;
7278edbede9SRichard Röjfors 		timberdale_xspi_platform_data.devices =
7288edbede9SRichard Röjfors 			timberdale_spi_8bit_board_info;
7298edbede9SRichard Röjfors 		timberdale_xspi_platform_data.num_devices =
7308edbede9SRichard Röjfors 			ARRAY_SIZE(timberdale_spi_8bit_board_info);
7318edbede9SRichard Röjfors 	} else {
7328edbede9SRichard Röjfors 		timberdale_xspi_platform_data.bits_per_word = 16;
7338edbede9SRichard Röjfors 		timberdale_xspi_platform_data.devices =
7348edbede9SRichard Röjfors 			timberdale_spi_16bit_board_info;
7358edbede9SRichard Röjfors 		timberdale_xspi_platform_data.num_devices =
7368edbede9SRichard Röjfors 			ARRAY_SIZE(timberdale_spi_16bit_board_info);
7378edbede9SRichard Röjfors 	}
7388edbede9SRichard Röjfors 
7398edbede9SRichard Röjfors 	ip_setup = priv->fw.config & TIMB_HW_VER_MASK;
7408edbede9SRichard Röjfors 	switch (ip_setup) {
7418edbede9SRichard Röjfors 	case TIMB_HW_VER0:
7428edbede9SRichard Röjfors 		err = mfd_add_devices(&dev->dev, -1,
7438edbede9SRichard Röjfors 			timberdale_cells_bar0_cfg0,
7448edbede9SRichard Röjfors 			ARRAY_SIZE(timberdale_cells_bar0_cfg0),
7450848c94fSMark Brown 			&dev->resource[0], msix_entries[0].vector, NULL);
7468edbede9SRichard Röjfors 		break;
7478edbede9SRichard Röjfors 	case TIMB_HW_VER1:
7488edbede9SRichard Röjfors 		err = mfd_add_devices(&dev->dev, -1,
7498edbede9SRichard Röjfors 			timberdale_cells_bar0_cfg1,
7508edbede9SRichard Röjfors 			ARRAY_SIZE(timberdale_cells_bar0_cfg1),
7510848c94fSMark Brown 			&dev->resource[0], msix_entries[0].vector, NULL);
7528edbede9SRichard Röjfors 		break;
7538edbede9SRichard Röjfors 	case TIMB_HW_VER2:
7548edbede9SRichard Röjfors 		err = mfd_add_devices(&dev->dev, -1,
7558edbede9SRichard Röjfors 			timberdale_cells_bar0_cfg2,
7568edbede9SRichard Röjfors 			ARRAY_SIZE(timberdale_cells_bar0_cfg2),
7570848c94fSMark Brown 			&dev->resource[0], msix_entries[0].vector, NULL);
7588edbede9SRichard Röjfors 		break;
7598edbede9SRichard Röjfors 	case TIMB_HW_VER3:
7608edbede9SRichard Röjfors 		err = mfd_add_devices(&dev->dev, -1,
7618edbede9SRichard Röjfors 			timberdale_cells_bar0_cfg3,
7628edbede9SRichard Röjfors 			ARRAY_SIZE(timberdale_cells_bar0_cfg3),
7630848c94fSMark Brown 			&dev->resource[0], msix_entries[0].vector, NULL);
7648edbede9SRichard Röjfors 		break;
7658edbede9SRichard Röjfors 	default:
7665588bd59SColin Ian King 		dev_err(&dev->dev, "Unknown IP setup: %d.%d.%d\n",
7678edbede9SRichard Röjfors 			priv->fw.major, priv->fw.minor, ip_setup);
7688edbede9SRichard Röjfors 		err = -ENODEV;
7698edbede9SRichard Röjfors 		goto err_mfd;
7708edbede9SRichard Röjfors 	}
7718edbede9SRichard Röjfors 
7728edbede9SRichard Röjfors 	if (err) {
7738edbede9SRichard Röjfors 		dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);
7748edbede9SRichard Röjfors 		goto err_mfd;
7758edbede9SRichard Röjfors 	}
7768edbede9SRichard Röjfors 
7778edbede9SRichard Röjfors 	err = mfd_add_devices(&dev->dev, 0,
7788edbede9SRichard Röjfors 		timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1),
7790848c94fSMark Brown 		&dev->resource[1], msix_entries[0].vector, NULL);
7808edbede9SRichard Röjfors 	if (err) {
7818edbede9SRichard Röjfors 		dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);
7828edbede9SRichard Röjfors 		goto err_mfd2;
7838edbede9SRichard Röjfors 	}
7848edbede9SRichard Röjfors 
7858edbede9SRichard Röjfors 	/* only version 0 and 3 have the iNand routed to SDHCI */
7868edbede9SRichard Röjfors 	if (((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER0) ||
7878edbede9SRichard Röjfors 		((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) {
7888edbede9SRichard Röjfors 		err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2,
7898edbede9SRichard Röjfors 			ARRAY_SIZE(timberdale_cells_bar2),
7900848c94fSMark Brown 			&dev->resource[2], msix_entries[0].vector, NULL);
7918edbede9SRichard Röjfors 		if (err) {
7928edbede9SRichard Röjfors 			dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);
7938edbede9SRichard Röjfors 			goto err_mfd2;
7948edbede9SRichard Röjfors 		}
7958edbede9SRichard Röjfors 	}
7968edbede9SRichard Röjfors 
7978edbede9SRichard Röjfors 	kfree(msix_entries);
7988edbede9SRichard Röjfors 
7998edbede9SRichard Röjfors 	dev_info(&dev->dev,
8008edbede9SRichard Röjfors 		"Found Timberdale Card. Rev: %d.%d, HW config: 0x%02x\n",
8018edbede9SRichard Röjfors 		priv->fw.major, priv->fw.minor, priv->fw.config);
8028edbede9SRichard Röjfors 
8038edbede9SRichard Röjfors 	return 0;
8048edbede9SRichard Röjfors 
8058edbede9SRichard Röjfors err_mfd2:
8068edbede9SRichard Röjfors 	mfd_remove_devices(&dev->dev);
8078edbede9SRichard Röjfors err_mfd:
8088edbede9SRichard Röjfors 	device_remove_file(&dev->dev, &dev_attr_fw_ver);
8098edbede9SRichard Röjfors err_create_file:
8108edbede9SRichard Röjfors 	pci_disable_msix(dev);
8118edbede9SRichard Röjfors err_msix:
812981c65a9SJulia Lawall 	kfree(msix_entries);
813981c65a9SJulia Lawall err_config:
8148edbede9SRichard Röjfors 	iounmap(priv->ctl_membase);
8158edbede9SRichard Röjfors err_ioremap:
8168edbede9SRichard Röjfors 	release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE);
8178edbede9SRichard Röjfors err_start:
8188edbede9SRichard Röjfors 	pci_disable_device(dev);
8198edbede9SRichard Röjfors err_enable:
8208edbede9SRichard Röjfors 	kfree(priv);
8218edbede9SRichard Röjfors 	return -ENODEV;
8228edbede9SRichard Röjfors }
8238edbede9SRichard Röjfors 
timb_remove(struct pci_dev * dev)8244740f73fSBill Pemberton static void timb_remove(struct pci_dev *dev)
8258edbede9SRichard Röjfors {
8268edbede9SRichard Röjfors 	struct timberdale_device *priv = pci_get_drvdata(dev);
8278edbede9SRichard Röjfors 
8288edbede9SRichard Röjfors 	mfd_remove_devices(&dev->dev);
8298edbede9SRichard Röjfors 
8308edbede9SRichard Röjfors 	device_remove_file(&dev->dev, &dev_attr_fw_ver);
8318edbede9SRichard Röjfors 
8328edbede9SRichard Röjfors 	iounmap(priv->ctl_membase);
8338edbede9SRichard Röjfors 	release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE);
8348edbede9SRichard Röjfors 
8358edbede9SRichard Röjfors 	pci_disable_msix(dev);
8368edbede9SRichard Röjfors 	pci_disable_device(dev);
8378edbede9SRichard Röjfors 	kfree(priv);
8388edbede9SRichard Röjfors }
8398edbede9SRichard Röjfors 
84036fcd06cSJingoo Han static const struct pci_device_id timberdale_pci_tbl[] = {
8418edbede9SRichard Röjfors 	{ PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) },
8428edbede9SRichard Röjfors 	{ 0 }
8438edbede9SRichard Röjfors };
8448edbede9SRichard Röjfors MODULE_DEVICE_TABLE(pci, timberdale_pci_tbl);
8458edbede9SRichard Röjfors 
8468edbede9SRichard Röjfors static struct pci_driver timberdale_pci_driver = {
8478edbede9SRichard Röjfors 	.name = DRIVER_NAME,
8488edbede9SRichard Röjfors 	.id_table = timberdale_pci_tbl,
8498edbede9SRichard Röjfors 	.probe = timb_probe,
85084449216SBill Pemberton 	.remove = timb_remove,
8518edbede9SRichard Röjfors };
8528edbede9SRichard Röjfors 
8530afb00e3SSachin Kamat module_pci_driver(timberdale_pci_driver);
8548edbede9SRichard Röjfors 
8558edbede9SRichard Röjfors MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
8568edbede9SRichard Röjfors MODULE_VERSION(DRV_VERSION);
8578edbede9SRichard Röjfors MODULE_LICENSE("GPL v2");
858