如何修改一个被占用的管脚,将其修改为普通gpio
评估板的F11_VOUT1_D0信号被用作了屏线的vd0_b0, 我们新设计的板子把这个管脚用作普通的GPIO去控制一个芯片,设备树里面没有找到F11_VOUT1_D0管脚的信息,GPIO8 0,地址0x4A0035dc等信息,我在设备树里添加了新的节点,代码如下。
写了一个新的驱动,通过insmod安装,demoApp设置这个GPIO的高低变化,可以安装,应用的时候会报错,错误内容见后面的表格;
如果管脚设置为led7 ,CTRL_CORE_PAD_MCASP2_AXR2,GPIO6_8,同样的方法、流程就没有问题,可以控制led7的闪烁。
请问我还有做什么吗?
mygpio56 {
pinctrl-names = "default";
pinctrl-0 = <&mygpio56_user_gpio>;
status = "okay";
compatible = "gpio567";
mygpio568 {
label = "mygpio569";
gpios = <&gpio8 0 GPIO_ACTIVE_LOW>;
};
};
mygpio56_user_gpio: mygpio56_user_gpio {
pinctrl-single,pins = <
DRA7XX_CORE_IOPAD(0x35dc, MUX_MODE14 | PIN_OUTPUT_PULLUP) /* gpio8-0 spi */
>;
};报错内容:
------------[ cut here ]------------
WARNING: CPU: 0 PID: 1330 at drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x25c/0x36c
44000000.ocp:L3 Custom Error: MASTER MPU TARGET L4_PER1_P3 (Read): Data Access in User mode during Functional access
Modules linked in: mygpio567(O) sha512_generic sha512_arm sha256_generic sha1_generic sha1_arm_neon sha1_arm md5 cbc xfrm_user xfrm4_tunnel ipcomp xfrm_ipcomp esp4 ah4 af_key xfrm_algo rfcomm bc_example(O) wlan btusb btrtl btbcm btintel xhci_plat_hcd pru_rproc pruss_intc xhci_hcd rpmsg_proto pruss bluetooth dwc3 udc_core rpmsg_rpc snd_soc_**_card snd_soc_**_card_utils pwm_fan snd_soc_omap_hdmi_audio pvrsrvkm(O) omap_aes_driver c_can_platform c_can omap_sham pruss_soc_bus can_dev omap_wdt ahci_platform libahci_platform libahci libata scsi_mod ti_vip ti_vpe ti_sc ti_csc ti_vpdma dwc3_omap extcon_core w1_therm ti_cal gpio_pisosr rtc_rx8010 ov5640_mipi omap_des ov5640 snd_soc_wm8960 omap_hdq wire spidev des_generic crypto_engine omap_remoteproc virtio_rpmsg_bus rpmsg_core remoteproc sch_fq_codel xr_usb_serial_common usbcore usb_common uio_module_drv(O) uio gdbserverproxy(O) cryptodev(O) cmemk(O)
CPU: 0 PID: 1330 Comm: hello Tainted: G D WO 4.9.41 #29
Hardware name: Generic DRA72X (Flattened Device Tree)
Backtrace:
[<c020b2d8>] (dump_backtrace) from [<c020b594>] (show_stack+0x18/0x1c)
r7:00000009 r6:60070193 r5:00000000 r4:c10229d0
[<c020b57c>] (show_stack) from [<c04ace60>] (dump_stack+0x8c/0xa0)
[<c04acdd4>] (dump_stack) from [<c022e4b8>] (__warn+0xec/0x104)
r7:00000009 r6:c0bcd6e0 r5:00000000 r4:ee413b40
[<c022e3cc>] (__warn) from [<c022e510>] (warn_slowpath_fmt+0x40/0x48)
r9:00000006 r8:ef1dd2d0 r7:c0bcd54c r6:00000002 r5:c0bcd60c r4:c0bcd6b0
[<c022e4d4>] (warn_slowpath_fmt) from [<c04dcd10>] (l3_interrupt_handler+0x25c/0x36c)
r3:ef1dd140 r2:c0bcd6b0
r4:80080003
[<c04dcab4>] (l3_interrupt_handler) from [<c027fd20>] (__handle_irq_event_percpu+0xb4/0x138)
r10:c101a4af r9:ef1d1200 r8:00000017 r7:ee413c64 r6:00000000 r5:ef1d1200
r4:ef1dd640
[<c027fc6c>] (__handle_irq_event_percpu) from [<c027fdc8>] (handle_irq_event_percpu+0x24/0x60)
r10:bf545360 r9:ee412000 r8:ef006000 r7:00000000 r6:c1008c34 r5:ef1d1200
r4:ef1d1200
[<c027fda4>] (handle_irq_event_percpu) from [<c027fe44>] (handle_irq_event+0x40/0x64)
r5:ef1d1260 r4:ef1d1200
[<c027fe04>] (handle_irq_event) from [<c02834f0>] (handle_fasteoi_irq+0xc0/0x190)
r7:00000000 r6:c1008c34 r5:ef1d1260 r4:ef1d1200
[<c0283430>] (handle_fasteoi_irq) from [<c027ef48>] (generic_handle_irq+0x2c/0x3c)
r7:00000000 r6:00000000 r5:00000017 r4:c0e5cde0
[<c027ef1c>] (generic_handle_irq) from [<c027f4d0>] (__handle_domain_irq+0x64/0xbc)
[<c027f46c>] (__handle_domain_irq) from [<c02014a0>] (gic_handle_irq+0x40/0x7c)
r9:ee412000 r8:fa213000 r7:fa212000 r6:ee413d20 r5:fa21200c r4:c1003424
[<c0201460>] (gic_handle_irq) from [<c020c138>] (__irq_svc+0x58/0x8c)
Exception stack(0xee413d20 to 0xee413d68)
3d20: 00000000 fa053000 00000001 bf5459c0 bf545770 c103408c 00000038 c1034074
3d40: ee1a9b40 ed31d360 bf545360 ee413d7c ee413c30 ee413d70 c02c0f18 bf545054
3d60: 60070013 ffffffff
r9:ee412000 r8:ee1a9b40 r7:ee413d54 r6:ffffffff r5:60070013 r4:bf545054
[<bf545020>] (mygpio_open ) from [<c05921bc>] (misc_open+0x15c/0x174)
[<c0592060>] (misc_open) from [<c0333fc0>] (chrdev_open+0xac/0x190)
r10:ee1a9b40 r9:ee413ea8 r8:ef342300 r7:ee1a9b40 r6:ed31d360 r5:ef342300
r4:c0a3ec80 r3:c0592060
[<c0333f14>] (chrdev_open) from [<c032d164>] (do_dentry_open.constprop.3+0x1ec/0x314)
r8:ee413f5c r7:c0333f14 r6:ee1a9b48 r5:ed31d360 r4:ee1a9b40
[<c032cf78>] (do_dentry_open.constprop.3) from [<c032e0a4>] (vfs_open+0x48/0x78)
r9:ee413ea8 r8:ee413f5c r7:eec023b8 r6:00000002 r5:ee1a9b40 r4:ee413ea8
[<c032e05c>] (vfs_open) from [<c033d1f4>] (path_openat+0x344/0xefc)
r5:00000000 r4:00000000
[<c033ceb0>] (path_openat) from [<c033f134>] (do_filp_open+0x6c/0xd0)
r10:00000000 r9:ee412000 r8:c0207d84 r7:00000001 r6:ee413f5c r5:ee413ea8
r4:00000003
[<c033f0c8>] (do_filp_open) from [<c032e458>] (do_sys_open+0x11c/0x1cc)
r7:fffff000 r6:ed384000 r5:ffffff9c r4:00000003
[<c032e33c>] (do_sys_open) from [<c032e528>] (SyS_open+0x20/0x24)
r9:ee412000 r8:c0207d84 r7:00000005 r6:00000000 r5:00000000 r4:be9d3b38
[<c032e508>] (SyS_open) from [<c0207be0>] (ret_fast_syscall+0x0/0x34)
---[ end trace 7e2b11ee0c31fa61 ]---
Unhandled fault: asynchronous external abort (0x1211) at 0x00000000
pgd = ee070680
*pgd=9fa38003, *pmd=00000000
systemd: systemd-journald.service: Failed with result 'core-dump'.
systemd: systemd-journald.service: Service has no hold-off time, scheduling restart.
systemd: Stopped Flush Journal to Persistent Storage.
systemd: Stopping Flush Journal to Persistent Storage...
systemd: Stopped Journal Service.
systemd: Starting Journal Service...
systemd-journald: File /run/log/journal/b9d28430c5bb428b8c75daa70d99e56a/system.journal corrupted or uncleanly shut down, renaming and replacing.
驱动源码:
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <generated/autoconf.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/cdev.h>
#include <linux/of.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/atomic.h>
//#include "mt-plat/mtgpio.h"
#include <linux/types.h>
//#include <mt-plat/mt_gpio.h>
//#include <mt-plat/mt_gpio_core.h>
//#include <mach/gpio_const.h>
/* 生命函数定义 */
static int mygpio_probe(struct platform_device *pdev);
static int mygpio_remove(struct platform_device *pdev);
static const struct of_device_id mygpio_of_match[] = {
{ .compatible = "gpio567", },
{},
};
static struct platform_driver mygpio_driver = {
.remove = mygpio_remove,
.probe = mygpio_probe,
.driver = {
.name = "myGPIO",
.owner = THIS_MODULE,
.of_match_table = mygpio_of_match,
},
};
#define GPIO_MUX_ADDR 0x4A0035dc
#define GPIO6_BASE_ADDR 0x48053000
#define GPIO_PIN_INDEX 0
#define GPIO_OE_OFFSET 0x134
#define GPIO_CLRDATAOUT_OFFSET 0x190
#define GPIO_SETDATAOUT_OFFSET 0x194
u32 reg_vir_addr;
static void config_gpio_muxmode(void)
{
u32 reg_vir;
printk("my_dev_muxmode\n");
reg_vir = (u32)ioremap_nocache(GPIO_MUX_ADDR, 0x20);
if (!reg_vir) {
printk(": ctrl register remapping failed");
}
//__raw_writel(0xE, reg_vir +0);
*(unsigned int *)(reg_vir)= 0x0e;//gpio
iounmap((void *)reg_vir);
//
}
static int mygpio_open(struct inode *inode, struct file *file)
{
printk("MyGPIO OPen. \r\n");
(*( unsigned int *)(reg_vir_addr + GPIO_CLRDATAOUT_OFFSET)) |= 1 << GPIO_PIN_INDEX;
(*( unsigned int *)(reg_vir_addr + GPIO_OE_OFFSET)) &= ~(1<<GPIO_PIN_INDEX);
(*( unsigned int *)(reg_vir_addr + GPIO_SETDATAOUT_OFFSET)) |= 1 << GPIO_PIN_INDEX;
return 0;
}
static ssize_t my_dev_write(struct file *file,const char __user *buf,size_t count,loff_t *offset)
{
#if 0
int ret;
ret = copy_from_user(&val,buf,count);
if(ret<0)
{
printk("ret=%d\n",ret);
return ret;
}
printk("my_dev_read\n");
return 0;
#endif
int ret,val;
char temp;
char status=0;
memset(temp,0,16);
ret=copy_from_user(temp,buf,count);
if(ret<0)
{
printk("ret=%d\n",ret);
status=-EFAULT;
goto err;
}
val=**_strtoul(temp,NULL,0);
if(val >= 1)
{
*( unsigned int *)(reg_vir_addr + GPIO_SETDATAOUT_OFFSET) |= 1 << GPIO_PIN_INDEX;
//gpio_set_value(gpio_led_pin,1);
}
else
{
*( unsigned int *)(reg_vir_addr + GPIO_CLRDATAOUT_OFFSET)|= 1 << GPIO_PIN_INDEX;
//gpio_set_value(gpio_led_pin,0);
}
if(!status)
status = count;
err:
return status;
}
static int mygpio_release(struct inode *inode, struct file *file)
{
printk("MyGPIO Release. \r\n");
return 0;
}
static long mygpio_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
printk("MyGPIO Ioctl. \r\n");
printk("MyGPIO cmd=%d \r\n", cmd);
return 0;
}
static const struct file_operations mygpio_fops = {
/* .owner = THIS_MODULE, */
.open = mygpio_open,
.write =my_dev_write,
.release = mygpio_release,
.unlocked_ioctl = mygpio_unlocked_ioctl,
};
static struct miscdevice mygpio_device = {
.minor = MISC_DYNAMIC_MINOR, //动态设备号
.name = "myGPIO",
.fops = &mygpio_fops,
};
/* My GPIO probe */
static int mygpio_probe(struct platform_device *pdev)
{//
int ret = 0;
unsigned int outvalue;
printk("MyGPIO Probe. \r\n");
ret = misc_register(&mygpio_device);
if (ret != 0 )
printk("myGPIO: mygpio_device register failed\n");
struct device_node *dn;
//1.通过节点名字查找指定的节点驱动程序里面调用of_get_address,提示没有?
dn = of_find_node_by_name(NULL,"mygpio56");
if(dn==NULL)
{
printk("of_find_node_by_name err \r\n");
}
else
{
//of_find_node_by_name :mygpio56 /mygpio56 <NULL> mygpio568compatible
// printk("of_find_node_by_name :%s %s %s%s %s %s\r\n",dn->name,dn->full_name,dn->type,dn->child->name,dn->properties->name, dn->properties->next->name);
of_property_read_u32_array(dn->child,dn->child->properties->next->name,outvalue,3);
//读取属性中 u8、 u16、 u32 和 u64 类型的数组数据,比如大多数的 reg 属性都是数组数据
printk("%s {\n",dn->name);
printk(" %s = \" %s \" ;\n",dn->properties->name,dn->properties->value);
printk(" %s = \" %s \" ;\n",dn->properties->next->name,dn->properties->next->value);
printk(" %s {\n",dn->child->name);
printk(" %s = \" %s \" ;\n",dn->child->properties->name,dn->child->properties->value);
printk(" %s = < %x %x %x > ;\n",dn->child->properties->next->name,outvalue,outvalue,outvalue);
printk("};\n};\n");
}
/// u64 size; unsigned int flags;
//unsigned int *addr;
// addr = of_get_address(dn->child, 0, size, flags);
//of_translate_address(dn->child, const __be32 *in_addr);
//2. 通过 device_type 属性查找指定的节点,节点对应的 type 字符串,也就是 device_type 属性值。
//struct device_node *of_find_node_by_type(struct device_node *from, const char *type)
//3. 根据 device_type 和 compatible 这两个属性查找指定的节点struct device_node *of_find_compatible_node(struct device_node *from,const char *type,const char *compatible)
//4 通过 of_device_id 匹配表来查找指定的节点struct device_node *of_find_matching_node_and_match(struct device_node *from,const struct of_device_id *matches,const struct of_device_id **match)matches: of_device_id 匹配表,也就是在此匹配表里面查找节点。match: 找到的匹配的 of_device_id。
return ret;
}
static int mygpio_remove(struct platform_device *pdev)
{
int err;
printk("MyGPIO remove. \r\n");
misc_deregister(&mygpio_device);
return err;
}
static int __init my_gpio_init(void)
{
int ret = 0;
printk("my_gpio_init. \r\n");
printk("Register MyGPIO platform_driverinit. \r\n");
reg_vir_addr = (u32)ioremap_nocache(GPIO6_BASE_ADDR, 0x800);
if (!reg_vir_addr) {
printk(": ctrl addr remapping failed");
}
config_gpio_muxmode();
ret = platform_driver_register(&mygpio_driver);
if(ret != 0 )
printk("unable to register MyGPIO driver.\n");
return ret;
}
/*---------------------------------------------------------------------------*/
static void __exit my_gpio_exit(void)
{
printk("my_gpio_exit. \r\n");
iounmap((void *)reg_vir_addr);
platform_driver_unregister(&mygpio_driver);
}
subsys_initcall(my_gpio_init);
/*module_init(my_gpio_init);*/
module_exit(my_gpio_exit);
MODULE_AUTHOR("zue");
MODULE_DESCRIPTION("MY General Purpose Driver (GPIO)");
MODULE_LICENSE("GPL v2");
/*
insmod newled
my_gpio_init.
MyGPIO Probe.compatible = "gpio567"; 匹配才执行
//
rmmod newled
my_gpio_exit.
MyGPIO remove.
app open-->open
write-->write
close--->release
*/
&gpio8 {
ti,no-reset-on-init;
};
这种操作不起作用呢,如果起作用,GPIO8对应的是屏显示,屏应该不显示内容才对
页:
[1]