Created
May 14, 2015 01:41
-
-
Save itrobotics/8b7f65b5f55540735ad3 to your computer and use it in GitHub Desktop.
a linux driver example code to demo platform_driver of Raspberry Pi which simple show the SPI-FLASH ID
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Simple Character Device Driver Module for Raspberry Pi. | |
#include <linux/module.h> | |
#include <linux/string.h> | |
#include <linux/fs.h> | |
#include <asm/uaccess.h> | |
#include <linux/init.h> | |
#include <linux/cdev.h> | |
#include <linux/device.h> | |
#include <linux/kernel.h> | |
#include <linux/errno.h> | |
#include <linux/io.h> | |
#include <linux/sched.h> | |
#include <linux/interrupt.h> | |
#include <linux/list.h> | |
#include <linux/irq.h> | |
#include <linux/slab.h> | |
#include <linux/gpio.h> | |
#include <linux/platform_device.h> | |
#include <mach/platform.h> | |
#include <mach/gpio.h> | |
#include <linux/time.h> | |
#include <linux/delay.h> | |
#include <linux/spi/spi.h> | |
#include <linux/io.h> | |
// | |
// 這裡使用arch/arm/mach-bcm2708/bcm2708.c 裡面已經準備好的platform_device for spi | |
// | |
#define MY_DEV_NAME "bcm2708_spi" | |
// ref to arch/arm/mach-bcm2708/include/platform.h | |
#define BCM2708_PERI_BASE 0x20000000 | |
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) | |
//#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) | |
/* ********************************************* | |
* PLATFORM DRIVER | |
* location : arch/driver/ | |
* ********************************************* | |
* */ | |
// -- PROBE | |
static int MY_SPI_MASTER_probe(struct platform_device *pdev) | |
{ | |
// get resource | |
struct resource *regs; | |
u32 *gpio ; | |
u32 *spi_base; | |
u32 *spi_fifo ; | |
int rx_len, tx_len; | |
u32 msg[6]; | |
u32 cmd[6]; | |
int i ; | |
i = 6; | |
while(i--)msg[i] = 0; | |
printk("my spi master probe\n"); | |
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
if (!regs) { | |
dev_err(&pdev->dev, "could not get IO memory\n"); | |
return -ENXIO; | |
} | |
// -- init_pinmode | |
// GPIO07=CE1 ; GPIO08=CE0 ; GPIO09=MISO ; GPIO10=MOSI ; GPIO11=CLK | |
gpio = ioremap(GPIO_BASE, SZ_16K); | |
printk("gpio:%p\n", gpio); | |
*gpio &=~((1<<21) | (1<<22) | (1<<23)); // GPIO07 as input | |
*gpio &=~((1<<24) | (1<<25) | (1<<26)); // GPIO08 as input | |
*gpio &=~((1<<27) | (1<<28) | (1<<29)); // GPIO09 as input | |
*(gpio+1) &=~((1<<0 ) | (1<<1 ) | (1<<2 )); // GPIO10 as input | |
*(gpio+1) &=~((1<<3 ) | (1<<4 ) | (1<<5 )); // GPIO10 as input | |
*gpio |= ( (1<<23)); // GPIO07 as alt0:SPI | |
*gpio |= ( (1<<26)); // GPIO08 as alt0:SPI | |
*gpio |= ( (1<<29)); // GPIO09 as alt0:SPI | |
*(gpio+1) |= ( (1<<2 )); // GPIO10 as alt0:SPI | |
*(gpio+1) |= ( (1<<5 )); // GPIO10 as alt0:SPI | |
iounmap(gpio); | |
// -- initialise the spi master hardware | |
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
if (!regs) { | |
dev_err(&pdev->dev, "could not get IO memory\n"); | |
return -ENXIO; | |
} | |
// get the spi base register | |
spi_base = ioremap(regs->start, resource_size(regs)); | |
if (!spi_base) { | |
dev_err(&pdev->dev, "could not remap memory\n"); | |
return 0; | |
} | |
printk("spi_base:%p\n", spi_base); | |
*spi_base = 0x00; | |
*spi_base |= ((1<<4) | (1<<5)); // clear tx,rx fifo | |
*spi_base &=~((1<<2) | (1<<3)); // setup SPI mode 0 : CPOL and CPHA = 0 | |
*(spi_base + 0x08/4 ) = 0x00; // setup CLK_DIV as 65535 | |
*(spi_base) &=~((1<<0) | (1<<1));// chip select :CS0 | |
*(spi_base) &=~( 1<<21) ; // CSPOL0 | |
// Try to Read the Company ID and Device ID from the spi0.0 | |
spi_fifo = spi_base + 0x0004/4; | |
// clear tx,rx fifo | |
*spi_base |= ((1<<4) | (1<<5)); // clear tx,rx fifo | |
*spi_base |= (1<<7); // set TA | |
// transaction: | |
rx_len = 0; | |
tx_len = 0; | |
cmd[0] = 0x90; | |
cmd[1] = 0x90; | |
cmd[2] = 0x90; | |
cmd[3] = 0x00; | |
cmd[4] = 0x00; | |
cmd[5] = 0x00; | |
while((rx_len < 6) || (tx_len < 6)){ | |
while((readl(spi_base) & (1<<18))&& (tx_len < 6) ){ | |
writel(cmd[tx_len],spi_fifo); | |
tx_len ++; | |
} | |
while((readl(spi_base) & (1<<17))&& (rx_len < 6) ){ | |
msg[rx_len] = readl(spi_fifo); | |
rx_len++; | |
} | |
} | |
*spi_base &=~(1<<7); // clear TA | |
iounmap(spi_base); | |
for(i=0 ;i<6 ;i++ ){ | |
printk("msg[%d]=%X\n", i,msg[i]); | |
} | |
return 0; | |
} | |
// -- REMOVE | |
static int MY_SPI_MASTER_remove(struct platform_device *pdev) | |
{ | |
return 0; | |
} | |
// -- PLATFORM DRIVER OBJECT | |
static struct platform_driver MY_SPI_MASTER_driver= { | |
.driver = { | |
.name = MY_DEV_NAME, | |
.owner = THIS_MODULE, | |
}, | |
.probe = MY_SPI_MASTER_probe, | |
.remove = MY_SPI_MASTER_remove, | |
}; | |
// -- Module INIT | |
static int __init MY_SPI_MASTER_init(void) | |
{ | |
printk("my spi master init\n"); | |
return platform_driver_probe(&MY_SPI_MASTER_driver, MY_SPI_MASTER_probe); | |
} | |
static void __exit MY_SPI_MASTER_exit(void) | |
{ | |
printk("my spi master exit\n"); | |
platform_driver_unregister(&MY_SPI_MASTER_driver); | |
} | |
module_init(MY_SPI_MASTER_init); | |
module_exit(MY_SPI_MASTER_exit); | |
MODULE_DESCRIPTION("Platform device and driver example"); | |
MODULE_AUTHOR("ITTraining"); | |
MODULE_LICENSE("GPL v2"); | |
//MODULE_ALIAS("platform:" MY_SPI_MASTER_PLATFORM_DEV_NAME); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment