Using SPI in a kernel module
Mykhail Lodygin
mishal at softerra.com
Sun Jun 27 17:26:53 EDT 2010
Invocation sequence is the same as described in ek_spi_devices. So since there is no YOUR driver in ek_spi_devices - i can't say when it would be called - for now - never.
which device? - you define it by setting .chip_select, i believe.
You could see all calls - just set verbosity to debug function in the
configuration.
On 06/27/2010 11:55 PM, Alfredo Quesada Sánchez wrote:
> There are a few compiled files in that directory (more preciselly is arch/arm/mach-at91), including:
>
> - board-XXX.c (well, the name of the board)
>
> MACHINE_START(AT91SAM9G45EKES, "Atmel AT91SAM9G45-EKES")
> /* Maintainer: Atmel */
> .phys_io = AT91_BASE_SYS,
> .io_pg_offst = (AT91_VA_BASE_SYS>> 18)& 0xfffc,
> .boot_params = AT91_SDRAM_BASE + 0x100,
> .timer =&at91sam926x_timer,
> .map_io = ek_map_io,
> .init_irq = ek_init_irq,
> .init_machine = ek_board_init,
> MACHINE_END
>
> In this file there is:
>
> /*
> * SPI devices.
> */
> static struct spi_board_info ek_spi_devices[] = {
> { /* DataFlash chip */
> .modalias = "mtd_dataflash",
> .chip_select = 0,
> .max_speed_hz = 15 * 1000 * 1000,
> .bus_num = 0,
> },
> };
>
> And in ek_board_init I can see a call to:
>
> /* SPI */
> at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
>
>
> This function is in at91sam9g45_devices.c (also compiled), also having:
>
> static struct resource spi0_resources[] = {
> [0] = {
> .start = AT91SAM9G45_BASE_SPI0,
> .end = AT91SAM9G45_BASE_SPI0 + SZ_16K - 1,
> .flags = IORESOURCE_MEM,
> },
> [1] = {
> .start = AT91SAM9G45_ID_SPI0,
> .end = AT91SAM9G45_ID_SPI0,
> .flags = IORESOURCE_IRQ,
> },
> };
>
> static struct platform_device at91sam9g45_spi0_device = {
> .name = "atmel_spi",
> .id = 0,
> .dev = {
> .dma_mask =&spi_dmamask,
> .coherent_dma_mask = DMA_BIT_MASK(32),
> },
> .resource = spi0_resources,
> .num_resources = ARRAY_SIZE(spi0_resources),
> };
>
> static const unsigned spi0_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PB18, AT91_PIN_PB19, AT91_PIN_PD27 };
>
> static struct resource spi1_resources[] = {
> [0] = {
> .start = AT91SAM9G45_BASE_SPI1,
> .end = AT91SAM9G45_BASE_SPI1 + SZ_16K - 1,
> .flags = IORESOURCE_MEM,
> },
> [1] = {
> .start = AT91SAM9G45_ID_SPI1,
> .end = AT91SAM9G45_ID_SPI1,
> .flags = IORESOURCE_IRQ,
> },
> };
>
> static struct platform_device at91sam9g45_spi1_device = {
> .name = "atmel_spi",
> .id = 1,
> .dev = {
> .dma_mask =&spi_dmamask,
> .coherent_dma_mask = DMA_BIT_MASK(32),
> },
> .resource = spi1_resources,
> .num_resources = ARRAY_SIZE(spi1_resources),
> };
>
> static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB17, AT91_PIN_PD28, AT91_PIN_PD18, AT91_PIN_PD19 };
>
> void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
> {
> int i;
> unsigned long cs_pin;
> short enable_spi0 = 0;
> short enable_spi1 = 0;
>
> /* Choose SPI chip-selects */
> for (i = 0; i< nr_devices; i++) {
> if (devices[i].controller_data)
> cs_pin = (unsigned long) devices[i].controller_data;
> else if (devices[i].bus_num == 0)
> cs_pin = spi0_standard_cs[devices[i].chip_select];
> else
> cs_pin = spi1_standard_cs[devices[i].chip_select];
>
> if (devices[i].bus_num == 0)
> enable_spi0 = 1;
> else
> enable_spi1 = 1;
>
> /* enable chip-select pin */
> at91_set_gpio_output(cs_pin, 1);
>
> /* pass chip-select pin to driver */
> devices[i].controller_data = (void *) cs_pin;
> }
>
> spi_register_board_info(devices, nr_devices);
>
> /* Configure SPI bus(es) */
> if (enable_spi0) {
> at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI0_MISO */
> at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI0_MOSI */
> at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI0_SPCK */
>
> at91_clock_associate("spi0_clk",&at91sam9g45_spi0_device.dev, "spi_clk");
> platform_device_register(&at91sam9g45_spi0_device);
> }
> if (enable_spi1) {
> at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_MISO */
> at91_set_A_periph(AT91_PIN_PB15, 0); /* SPI1_MOSI */
> at91_set_A_periph(AT91_PIN_PB16, 0); /* SPI1_SPCK */
>
> at91_clock_associate("spi1_clk",&at91sam9g45_spi1_device.dev, "spi_clk");
> platform_device_register(&at91sam9g45_spi1_device);
> }
> }
>
> To summarize, in the end platform_device_register should be called for SPI 0 (as you can see the board has 2 SPI channels).
>
>
> So.. assuming this is working as expected, when should i see a call to my driver's probe function? and.. which spi_device will be passed as parameter? (there is only 1 registered, but for this question let's assume that i have more spi devices registered).
>
> Regards
>
>
>> Hello
>> How about specifying correct data (for your particular
>> board) in the
>> machine-specific
>> code?(arch/your_arch/mach-your_machine/your_machine.c)
>> Basically it is enough for the system to invoke proper
>> probes.
>> Mikhail
>>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100628/edc6638e/attachment-0001.html>
More information about the linux-arm-kernel
mailing list