linux 内核gpio模拟spi (3线24bit模式)

代码如下:

/*
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/sched.h>

#include <linux/spi/spi.h>
#include <linux/spi/eeprom.h>
//#include <mach/io.h>
#include <linux/gpio.h>

/* define spi gpio*/
#define TXD_PORT       109
#define CLK_PORT       108
#define CS_PORT        111
#define RXD_PORT       110
#define SSD2828_RESET_PIN 39 // 51


#define INVALID_GPIO -1
#define GPIO_HIGH 1
#define GPIO_LOW 0

#define CS_OUT()        gpio_direction_output(CS_PORT, 1)
#define CS_SET()        gpio_set_value(CS_PORT, GPIO_HIGH)
#define CS_CLR()        gpio_set_value(CS_PORT, GPIO_LOW)
#define CLK_OUT()       gpio_direction_output(CLK_PORT, 1)
#define CLK_SET()       gpio_set_value(CLK_PORT, GPIO_HIGH)
#define CLK_CLR()       gpio_set_value(CLK_PORT, GPIO_LOW)
#define TXD_OUT()       gpio_direction_output(TXD_PORT, 1)
#define TXD_SET()       gpio_set_value(TXD_PORT, GPIO_HIGH)
#define TXD_CLR()       gpio_set_value(TXD_PORT, GPIO_LOW)
#define RXD_INPUT()	gpio_direction_input(RXD_PORT)
#define RXD_GET()  	gpio_get_value(RXD_PORT) 

/* spi write a data frame,type mean command or data 
	3 wire 24 bit SPI interface
*/

static void spi_send_data(unsigned int data)
{
	unsigned int i;

	CS_SET();
	udelay(1);
	CLK_SET();
	TXD_SET();

	CS_CLR();
	udelay(1);

	for (i = 0; i < 24; i++)
	{
		//udelay(1); 
		CLK_CLR();
		udelay(1);
		if (data & 0x00800000)
		{
			TXD_SET();
		} else
		{
			TXD_CLR();
		}
		udelay(1);
		CLK_SET();
		udelay(1);
		data <<= 1;
	}

	TXD_SET();
	CS_SET();
}

static void spi_recv_data(unsigned int *data)
{
	unsigned int i = 0, temp = 0x73;	//read data

	CS_SET();
	udelay(1);
	CLK_SET();
	TXD_SET();

	CS_CLR();
	udelay(1);

	for (i = 0; i < 8; i++)		// 8 bits Data
	{
		udelay(1);
		CLK_CLR();
		if (temp & 0x80)
			TXD_SET();
		else
			TXD_CLR();
		temp <<= 1;
		udelay(1);
		CLK_SET();
		udelay(1);
	}
	udelay(1);
	temp = 0;
	for (i = 0; i < 16; i++)	// 16 bits Data
	{
		udelay(1);
		CLK_CLR();
		udelay(1);
		CLK_SET();
		udelay(1);
		temp <<= 1;
		if ((RXD_GET() >> 14) == GPIO_HIGH) //get pin value for mx6sl
		{
		printk("rxd_get high\n");
			temp |= 0x01;
		}

	}

	TXD_SET();
	CS_SET();
	*data = temp;
}

#define DEVIE_ID (0x70 << 16)
void send_ctrl_cmd(unsigned int cmd)
{
	unsigned int out = (DEVIE_ID | cmd);
	spi_send_data(out);
}

static void send_data_cmd(unsigned int data)
{
	unsigned int out = (DEVIE_ID | (0x2 << 16) | data);
	spi_send_data(out);
}

unsigned int ssd2828_read_register(unsigned int reg)
{
	unsigned int data = 0;
	send_ctrl_cmd(reg);
	spi_recv_data(&data);
	return (data & 0xffff);
}

void ssd2828_set_register(unsigned int reg_and_value)
{
	send_ctrl_cmd(reg_and_value >> 16);
	send_data_cmd(reg_and_value & 0x0000ffff);
}



//ed

int ssd2828_probe(struct spi_device *spi)
{

	int err;
	int sr;
	int addrlen;
	int i = 0, ret = 0;
	unsigned char send[3] = { 0, 0, 0 };
	int value = 0;

	printk("*************ssd2828 probe *************\n");

	ret = gpio_request(SSD2828_RESET_PIN, NULL);  //RESET
	if (ret != 0)
	{
		gpio_free(SSD2828_RESET_PIN);
		printk("reset pin 39 request fail\n");
		return -EIO;
	}
	gpio_direction_output(SSD2828_RESET_PIN, 1);
	
	ret = gpio_request(CLK_PORT, NULL);  //CLK
	if (ret != 0)
	{
		gpio_free(CLK_PORT);
		printk("clk pin 108 request fail\n");
		return -EIO;
	}
	gpio_direction_output(CLK_PORT, 1);

	ret = gpio_request(TXD_PORT, NULL); //OUTPUT MOSI
	if (ret != 0)
	{
		gpio_free(TXD_PORT);
		printk("TXD_PORT 109 request fail\n");
		return -EIO;
	}
	gpio_direction_output(TXD_PORT, 1);

	ret = gpio_request(RXD_PORT, NULL);  //INPUT MISO
	if (ret != 0)
	{
		gpio_free(RXD_PORT);
		printk("rxd pin 110 request fail\n");
		return -EIO;
	}
	gpio_direction_input(RXD_PORT);
	
	ret = gpio_request(CS_PORT, NULL);  //CS
	if (ret != 0)
	{
		gpio_free(CS_PORT);
		printk("cs pin111 request fail\n");
		return -EIO;
	}
	gpio_direction_output(CS_PORT, 1);
        
	/* reset 2828 */
	gpio_direction_output(SSD2828_RESET_PIN, 1);
	gpio_set_value(SSD2828_RESET_PIN, GPIO_LOW);
	msleep(2000);				//sleep 200ms
	gpio_set_value(SSD2828_RESET_PIN, GPIO_HIGH);

	/* Chip description */
	value = ssd2828_read_register(0xb0);	//send 0x7000b0

	printk("read 0x7000b0 is:0x %0x\n", value);
	ret=gpio_get_value(RXD_PORT);
	printk("read port is %d\n",ret);
	return 0;
}

static int ssd2828_remove(struct spi_device *spi)
{
	printk("ssd2828 remove\n");
	return 0;
}

/*-------------------------------------------------------------------------*/

static struct spi_driver ssd2828_driver = {
	.driver = {
			   .name = "ssd2828",
			   .owner = THIS_MODULE,
			   },
	.probe = ssd2828_probe,
	.remove = ssd2828_remove,
};

static int __init ssd2828_init(void)
{
	int ret = 0;
	ssd2828_probe(NULL);
	return ret;
}

static void __exit ssd2828_exit(void)
{
	printk("ssd2828 exit\n");
	gpio_free(39);
	gpio_free(108);
	gpio_free(109);
	gpio_free(110);
	gpio_free(111);
}

module_init(ssd2828_init);
module_exit(ssd2828_exit);

MODULE_DESCRIPTION("Driver for ssd2828");
MODULE_AUTHOR("SSL");
MODULE_LICENSE("GPL");


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值