spidev.c driver on the ppc8247 (kernel 2.6.27.19)

Daniel Ng daniel.ng1234 at gmail.com
Wed Mar 18 18:36:30 EST 2009


Hi,

I'm trying to get the spidev.c driver working in Kernel 2.6.27.19 on a ppc8247.

Firstly, would I need to convert it to an 'of'-style driver?

Assuming this is the case, I've changed spidev_init() to use
of_register_platform_driver() with what I think is an appropriate
parameter:

static struct of_platform_driver spidev_spi = {
    .name         = "spidev",
    .match_table  = spidev_match,
    .probe        = spidev_probe,
    .remove       = __devexit_p(spidev_remove),
};

spidev_probe() now looks like the below. I've had to change the
spidev_probe() function signature, which meant I needed to use
to_spi_device() in the function (there are no other changes).

static int __devinit spidev_probe(struct of_device *ofdev, const
struct of_device_id *match)
{
	struct spidev_data	*spidev;
	int			status;
	unsigned long		minor;
                struct spi_device *spi;

                spi = to_spi_device(&ofdev->dev);

	/* Allocate driver data */
	spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);
	if (!spidev)
		return -ENOMEM;

	/* Initialize the driver data */
	spidev->spi = spi;
	spin_lock_init(&spidev->spi_lock);
	mutex_init(&spidev->buf_lock);

	INIT_LIST_HEAD(&spidev->device_entry);

	/* If we can allocate a minor number, hook up this device.
	 * Reusing minors is fine so long as udev or mdev is working.
	 */
	mutex_lock(&device_list_lock);
	minor = find_first_zero_bit(minors, N_SPI_MINORS);
	if (minor < N_SPI_MINORS) {
		struct device *dev;

		spidev->devt = MKDEV(SPIDEV_MAJOR, minor);

		dev = device_create_drvdata(spidev_class, &spi->dev,
				spidev->devt, spidev,
				"spidev%d.%d",
				spi->master->bus_num, spi->chip_select);
    printk("spidev_probe(): CREATED spidev%d.%d\n",
spi->master->bus_num, spi->chip_select);
		status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
.
.
/////// (the rest of this function is unchanged)
.

}

It all executes ok until the above call to device_create_drvdata(),
where it crashes (see below). Can anyone explain why?

Can I still use the 'old-style' device_create_drvdata() function with
the 'of new-style' driver framework?

Am I going about this the right way?

Unable to handle kernel paging request for data at address 0x00000120
Faulting instruction address: 0xc028e484
Oops: Kernel access of bad area, sig: 11 [#1]
PREEMPT XXX
NIP: c028e484 LR: c028e478 CTR: c01511c8
REGS: c1819d60 TRAP: 0300   Not tainted  (2.6.27.19-800-OS-03050107)
MSR: 00009032 <EE,ME,IR,DR>  CR: 42044024  XER: 00000000
DAR: 00000120, DSISR: 20000000
TASK = c1814400[1] 'swapper' THREAD: c1818000
GPR00: c028e478 c1819e10 c1814400 0000000b 0000150c 0e400000 00000008 c0270000
GPR08: f0000038 00000000 0000150c c1818000 f0000020 fffffffe 01ff8000 00000000
GPR16: 01fed694 01ff56f0 00000000 00000000 00000000 00000000 c02d0000 c184ec10
GPR24: c02d2610 c1963288 c02d260c c02aafa4 00000000 ffffffed c1963280 c184ec10
NIP [c028e484] spidev_probe+0xec/0x1c8
LR [c028e478] spidev_probe+0xe0/0x1c8
Call Trace:
[c1819e10] [c028e478] spidev_probe+0xe0/0x1c8 (unreliable)
[c1819e40] [c01814a4] of_platform_device_probe+0x5c/0x84
[c1819e60] [c01552c8] driver_probe_device+0xe8/0x240
[c1819e90] [c01554a4] __driver_attach+0x84/0x88
[c1819eb0] [c01548fc] bus_for_each_dev+0x5c/0x98
[c1819ee0] [c01550a0] driver_attach+0x24/0x34
[c1819ef0] [c0154eac] bus_add_driver+0x1b4/0x220
[c1819f10] [c01557b4] driver_register+0x5c/0x158
[c1819f30] [c018136c] of_register_driver+0x54/0x70
[c1819f40] [c0289a28] spidev_init+0x6c/0xf8
[c1819f60] [c00038e8] do_one_initcall+0x38/0x188
[c1819fd0] [c0278180] kernel_init+0x8c/0xf8
[c1819ff0] [c000f6fc] kernel_thread+0x44/0x60
Instruction dump:
4be90481 2b83001f 7c7c1b78 419d00d8 64600e40 901e0000 3c60c027 38638f04
4bd8ea31 813f0120 80be0000 3ce0c027 <a9090120> 38e78f10 893f0128 7fe4fb78
---[ end trace 8d59482f3bf88fe6 ]---

Cheers,
Daniel



More information about the Linuxppc-dev mailing list