写一个LPC总线的master驱动
时间: 2024-05-12 07:13:23 浏览: 179
LPC总线是一种低速、低功耗的总线,常用于连接嵌入式系统中的外设。下面是一个LPC总线的master驱动的示例代码:
```c
#include <linux/module.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/delay.h>
#define LPC_IO_BASE 0x40000000 /* LPC总线基地址 */
#define LPC_SRAM_BASE 0x80000000 /* SRAM基地址 */
#define LPC_FLASH_BASE 0x90000000 /* FLASH基地址 */
/* LPC总线寄存器偏移量 */
#define LPC_IOREG_OFFSET 0x800
#define LPC_MEMREG_OFFSET 0x400
/* LPC总线寄存器定义 */
#define LPC_SC (LPC_IO_BASE + 0x000)
#define LPC_PIN (LPC_IO_BASE + 0x014)
#define LPC_PIN_DIR (LPC_IO_BASE + 0x018)
#define LPC_PIN_SEL (LPC_IO_BASE + 0x01C)
#define LPC_IRQ (LPC_IO_BASE + 0x020)
#define LPC_IRQ_SEL (LPC_IO_BASE + 0x024)
#define LPC_TIM_CTRL (LPC_IO_BASE + 0x028)
#define LPC_TIM_CNT (LPC_IO_BASE + 0x02C)
#define LPC_UART_CTRL (LPC_IO_BASE + 0x030)
#define LPC_UART_STAT (LPC_IO_BASE + 0x034)
#define LPC_UART_DATA (LPC_IO_BASE + 0x038)
#define LPC_UART_BAUD (LPC_IO_BASE + 0x03C)
#define LPC_GPIO0_DIR (LPC_IO_BASE + 0x040)
#define LPC_GPIO0_DATA (LPC_IO_BASE + 0x044)
#define LPC_GPIO1_DIR (LPC_IO_BASE + 0x048)
#define LPC_GPIO1_DATA (LPC_IO_BASE + 0x04C)
#define LPC_GPIO2_DIR (LPC_IO_BASE + 0x050)
#define LPC_GPIO2_DATA (LPC_IO_BASE + 0x054)
#define LPC_GPIO3_DIR (LPC_IO_BASE + 0x058)
#define LPC_GPIO3_DATA (LPC_IO_BASE + 0x05C)
#define LPC_MEM_CTRL (LPC_IO_BASE + 0x080)
#define LPC_MEM_ADDR0 (LPC_IO_BASE + 0x084)
#define LPC_MEM_ADDR1 (LPC_IO_BASE + 0x088)
#define LPC_MEM_ADDR2 (LPC_IO_BASE + 0x08C)
#define LPC_MEM_ADDR3 (LPC_IO_BASE + 0x090)
#define LPC_IOREG_CTRL (LPC_IO_BASE + LPC_IOREG_OFFSET)
#define LPC_IOREG_DATA (LPC_IO_BASE + LPC_IOREG_OFFSET + 4)
#define LPC_MEMREG_CTRL (LPC_IO_BASE + LPC_MEMREG_OFFSET)
#define LPC_MEMREG_DATA (LPC_IO_BASE + LPC_MEMREG_OFFSET + 4)
/* 定义LPC总线支持的访问类型 */
enum lpc_access_type {
LPCT_IO = 0, /* I/O访问 */
LPCT_MEM = 1, /* 存储器访问 */
};
/* 定义LPC总线master驱动结构体 */
struct lpc_master_driver {
struct device_driver driver;
enum lpc_access_type access_type;
};
static int lpc_master_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct lpc_master_driver *driver;
void __iomem *base;
u32 val;
/* 获取LPC总线信息 */
driver = dev_get_drvdata(dev);
if (!driver) {
dev_err(dev, "no driver data\n");
return -EINVAL;
}
/* 获取LPC总线基地址 */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "no LPC base address\n");
return -ENODEV;
}
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base)) {
dev_err(dev, "failed to ioremap LPC base address\n");
return PTR_ERR(base);
}
/* 初始化LPC总线控制寄存器 */
val = readl(base + LPC_IOREG_CTRL);
val &= ~(0x3 << 2); /* 清除访问类型位 */
val |= (driver->access_type << 2); /* 设置访问类型 */
writel(val, base + LPC_IOREG_CTRL);
return 0;
}
static int lpc_master_remove(struct platform_device *pdev)
{
return 0;
}
/* 定义LPC总线master驱动匹配表 */
static const struct of_device_id lpc_master_of_match[] = {
{ .compatible = "lpc-master", .data = &(struct lpc_master_driver){
.access_type = LPCT_IO,
} },
{ .compatible = "lpc-master-mem", .data = &(struct lpc_master_driver){
.access_type = LPCT_MEM,
} },
{},
};
MODULE_DEVICE_TABLE(of, lpc_master_of_match);
/* 定义LPC总线master驱动结构体 */
static struct platform_driver lpc_master_driver = {
.driver = {
.name = "lpc-master",
.of_match_table = lpc_master_of_match,
},
.probe = lpc_master_probe,
.remove = lpc_master_remove,
};
/* 初始化LPC总线master驱动 */
static int __init lpc_master_init(void)
{
return platform_driver_register(&lpc_master_driver);
}
module_init(lpc_master_init);
/* 卸载LPC总线master驱动 */
static void __exit lpc_master_exit(void)
{
platform_driver_unregister(&lpc_master_driver);
}
module_exit(lpc_master_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("LPC Master Driver");
```
这个驱动使用了Platform Driver框架,可以在设备树中定义LPC总线master驱动节点,例如:
```dts
lpc_master {
compatible = "lpc-master";
};
```
或者:
```dts
lpc_master_mem {
compatible = "lpc-master-mem";
};
```
这两个驱动分别用于I/O访问和存储器访问,可以根据需要选择。驱动会根据设备树的配置自动选择访问类型,并初始化LPC总线控制寄存器。
阅读全文