Table of Contents

flink on Phytec PCM032 Board (mpc5200)

The following example describes in detail how a Phytec PCM032 Board containing a mpc5200 and a FPGA is configured to be used with flink. The FPGA will contain a single channel PWM module and a single channel GPIO modul. flink was tested with the FPGA on the mpc5200io module as well as with an external FPGA connected through a SPI interface.

External FPGA connected through SPI interface

The pmc5200 offers a dedicated SPI (8 bit transfers) which can be routed onto the pins of the timer group or the PSC3 group. The PSC1, PSC2, PSC3 or PSC6 can operate as an SPI with 32 bit transfers.

Setup

Configure the FPGA

Proceed as described in flink VHDL.

Connect the FPGA with the SPI pins on the mpc5200.

Loading the kernel modules

There are several ways to properly drive the SPI from the mpc5200.

Configure pin multiplexing

The hardware SPI and can be routed onto several different pin groups. The PSC-SPI needs configuring of the port configuration register. Our current UBoot does not yet fully suppport device tree configuration, it must be done manually. These actions could be done in a board initialization file. We prefer to put it directly into the mod_init function of the flink_spi driver. The code below sets to port configuration register so that one of the PSC's pin groups runs in SPI mode.

	// use these declarations for platform specific initialization
	static const struct of_device_id mpc52xx_gpio_simple[] = {
		{ .compatible = "fsl,mpc5200-gpio", },
		{}
	};
	struct mpc52xx_gpio __iomem *gpio;
	struct device_node *np;
	u32 portConfig;
	u8 pscNum = 2;	// set to 1,2,3 or 6

	// use in case a PSC serves as SPI
	// set port configuration register of mpc5200
	np = of_find_matching_node(NULL, mpc52xx_gpio_simple);
	gpio = of_iomap(np, 0);
	of_node_put(np);
	if (!gpio) {
		printk(KERN_ERR "%s() failed, expect abnormal behavior\n", __func__);
		return -1;
	}
	portConfig = in_be32(&gpio->port_config);
	#if defined(DBG)
		printk(KERN_DEBUG "[%s] Current port config = 0x%x\n", MODULE_NAME, portConfig);
	#endif
	if (pscNum == 6) {
		portConfig |=  0x00700060;	// PSC6 is Codec/SPI
	} else if (pscNum >= 1 && pscNum <= 3) {
		portConfig &= ~(7 << ((pscNum-1)*4));
		portConfig |=  6 << ((pscNum-1)*4);
	} else {
		printk(KERN_ERR "[%s] Wrong PSC number\n", MODULE_NAME);
		return -1;
	}
	out_be32(&gpio->port_config, portConfig);
	#if defined(DBG)
		printk(KERN_DEBUG "[%s] New port config = 0x%x\n", MODULE_NAME, portConfig);
	#endif
	iounmap(gpio);

Similarly you could configure the PSC3 group that the hardware SPI is output on the pins PSC3_6 .. PSC3_9. In our system this is already done by UBoot.

Build into kernel

Compile kernel modules (see flink Linux Kernel Modules) and add them to your kernel image. Add a subnode flink_spi to your device tree under the node spi. In the compatible statement you must specify which protokoll driver to load (compatible = “flink_spi”). You can also specify the clock frequency. When booting the SPI-subsystem will automatically load a master driver (spi-mpc5200 or spi-mpc5200-psc) and the protokoll driver flink_spi.

Load manually

When loading the driver manually add the following code to the mod_init function of the flink_spi driver.

	struct spi_master *master;
	struct spi_device *dev;
	master = spi_busnum_to_master(num);	// use bus number of master
	if (!master) {
		printk(KERN_ERR "[%s] No master for this bus number\n", MODULE_NAME);
		goto exit;
	}
	dev = spi_new_device(master, &flinkInfo);

num must correspond to your master bus number. This will be 32766 for the hardware SPI and 1,2,3 or 6 for the PSC-SPI. You have to specify driver data as follows.

static struct spi_board_info flinkInfo = {
		.modalias = "flink_spi",
		.max_speed_hz = 2000000,
		.mode = SPI_MODE_1
};

When working with a PSC-SPI you would configure it to run with truly 32 bit transfers. Add the following lines:

	dev = spi_new_device(master, &flinkInfo);
	dev->bits_per_word = 32;
	spi_setup(dev);

Finally, compile kernel modules (see flink Linux Kernel Modules), transfer them to the target and load them:

insmod flink.ko
insmod flink_spi.ko

As we specified an info subdevice we can ommit the memory length when loading flink_lpb.ko.

Compile the flink library (see flink Userspace Library) together with several test applications. Transfer the library and the test application to the target. Make sure that your library path includes the actual location of your library. Run test applications such as lsflink, flinkdio or flinkpwm.

Onboard FPGA connected through Local Plus Bus

Setup

Configure the FPGA

Proceed as described in flink VHDL.

signaldirpin
clk_clkinPIN_H2
lpb_ack_noutPIN_T11
lpb_ad[31]bidirPIN_T6
lpb_ad[30]bidirPIN_N8
lpb_ad[29]bidirPIN_R9
lpb_ad[28]bidirPIN_T9
lpb_ad[27]bidirPIN_R8
lpb_ad[26]bidirPIN_T8
lpb_ad[25]bidirPIN_L8
lpb_ad[24]bidirPIN_L7
lpb_ad[23]bidirPIN_R7
lpb_ad[22]bidirPIN_T7
lpb_ad[21]bidirPIN_R5
lpb_ad[20]bidirPIN_T5
lpb_ad[19]bidirPIN_R4
lpb_ad[18]bidirPIN_T4
lpb_ad[17]bidirPIN_P4
lpb_ad[16]bidirPIN_P5
lpb_ad[15]bidirPIN_R3
lpb_ad[14]bidirPIN_T3
lpb_ad[13]bidirPIN_P11
lpb_ad[12]bidirPIN_N11
lpb_ad[11]bidirPIN_L11
lpb_ad[10]bidirPIN_M11
lpb_ad[9]bidirPIN_R14
lpb_ad[8]bidirPIN_T14
lpb_ad[7]bidirPIN_R13
lpb_ad[6]bidirPIN_T13
lpb_ad[5]bidirPIN_R12
lpb_ad[4]bidirPIN_T12
lpb_ad[3]bidirPIN_P13
lpb_ad[2]bidirPIN_P12
lpb_ad[1]bidirPIN_K10
lpb_ad[0]bidirPIN_K11
lpb_ale_ninPIN_R11
lpb_cs_n[0]inPIN_N10
lpb_intoutPIN_R6
lpb_oe_ninPIN_L9
lpb_rdwr_ninPIN_L10
lpb_ts_ninPIN_T10
reset_reset_ninPIN_N9

The pins for the PWM output and the GPIO have to be assigned according to your hardware. The FPGA can be loaded through the onboard PROM or through serial loading from the processor, see Installation von Emdebian Grip auf den Phytec phyCORE-MPC5200B.

Loading the kernel modules

Compile the Linux kernel modules (flink Linux Kernel Modules), transfer them to the target and load them with

insmod flink.ko
insmod flink_lpb.ko

As we specified an info subdevice we can ommit the memory length when loading flink_lpb.ko.

This step is the same as described under using the SPI.