質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Q&A

解決済

1回答

1754閲覧

Linuxの自作ドライバでinit関数が呼ばれません

hero1000

総合スコア56

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

0グッド

1クリップ

投稿2020/12/10 04:53

編集2020/12/10 05:22

#現在の状況
以前の質問に関連しているのですが、まだドライバが認識されず困っています。

デバイスツリーとドライバの関連付けについてはわかってきたのですが、関連づいているのにも関わらずドライバのinit関数やprobe関数が呼ばれません。エラーらしきものも出ていません。
(必ず通るところでdmesgに出力するようにしていますが、出力されません)
デバッグ出力レベルは調整済みです。

ちなみにmodprobeを使うと、正しく認識されているようです(lsmodで見ただけですが)。

以下、ソースコードです。

c

1#include <linux/delay.h> 2#include <linux/device.h> 3#include <linux/gpio/consumer.h> 4#include <linux/kernel.h> /*<-include printk.h */ 5#include <linux/module.h> 6#include <linux/mutex.h> 7#include <linux/of.h> 8#include <linux/of_device.h> 9#include <linux/of_gpio.h> 10#include <linux/slab.h> 11#include <linux/platform_device.h> 12#include <linux/spi/spi.h> 13#include <linux/uaccess.h> 14#include <linux/eeprom_93xx56.h> 15 16/* 17 * This supports access to SPI devices using normal userspace I/O calls. 18 * Note that while traditional UNIX/POSIX I/O semantics are half duplex, 19 * and often mask message boundaries, full SPI support requires full duplex 20 * transfers. There are several kinds of internal message boundaries to 21 * handle chipselect management and other protocol options. 22 * 23 * SPI has a character major number assigned. We allocate minor numbers 24 * dynamically using a bitmask. You must use hotplug tools, such as udev 25 * (or mdev with busybox) to create and destroy the /dev/spidevB.C device 26 * nodes, since there is no fixed association of minor numbers with any 27 * particular SPI bus or device. 28 */ 29#define SPIDEV_MAJOR 153 /* assigned */ 30#define N_SPI_MINORS 32 /* ... up to 256 */ 31 32#define OP_START 0x4 33#define OP_WRITE (OP_START | 0x1) 34#define OP_READ (OP_START | 0x2) 35#define ADDR_EWDS 0x00 36#define ADDR_ERAL 0x80 37#define ADDR_EWEN 0xC0 38 39#define ADDR_LEN_x8 (9) 40 41static struct class *eeprom_93xx56_class; 42 43struct eeprom_93xx56_dev { 44 dev_t devt; 45 spinlock_t spi_lock; 46 struct spi_device *spi; 47 struct eeprom_93xx56_platform_data *pdata; 48 struct list_head device_entry; 49 struct mutex lock; 50 struct mutex buf_lock; 51 int addrlen; 52 int size; 53 unsigned users; 54 u8 *tx_buffer; 55 u8 *rx_buffer; 56 u32 speed_hz; 57}; 58 59static LIST_HEAD(device_list); 60static DEFINE_MUTEX(device_list_lock); 61static unsigned bufsiz = 256; 62module_param(bufsiz, uint, S_IRUGO); 63MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message"); 64 65/*----------------------------- Module Define ------------------------------------------ */ 66static const struct of_device_id eeprom_93xx56_of_table[] = { 67 { .compatible = "microchip,eeprom-93xx56" }, 68 {}, 69}; 70MODULE_DEVICE_TABLE(of, eeprom_93xx56_of_table); 71 72static const struct spi_device_id eeprom_93xx56_id[] = { 73 { "93xx56-0", 0 }, 74 {}, 75}; 76MODULE_DEVICE_TABLE(spi, eeprom_93xx56_id); 77/* ------------------------------------------------------------------------------------- */ 78....中略.... 79static int eeprom_93xx56_probe_dt(struct spi_device *spi) 80{ 81 struct device_node *np = spi->dev.of_node; 82 struct eeprom_93xx56_platform_data *pd; 83 u32 tmp; 84 int gpio; 85 enum of_gpio_flags of_flags; 86 int ret; 87 88 pd = devm_kzalloc(&spi->dev, sizeof(*pd), GFP_KERNEL); 89 if (!pd) 90 return -ENOMEM; 91 92 ret = of_property_read_u32(np, "data-size", &tmp); 93 if (ret < 0) { 94 dev_err(&spi->dev, "data-size property not found\n"); 95 return ret; 96 } 97 98 if (tmp == 8) { 99 pd->flags |= EE_ADDR8; 100 } else if (tmp == 16) { 101 pd->flags |= EE_ADDR16; 102 } else { 103 dev_err(&spi->dev, "invalid data-size (%d)\n", tmp); 104 return -EINVAL; 105 } 106 107 if (of_property_read_bool(np, "read-only")) 108 pd->flags |= EE_READONLY; 109 110 gpio = of_get_named_gpio_flags(np, "select-gpios", 0, &of_flags); 111 if (gpio_is_valid(gpio)) { 112 unsigned long flags = 113 of_flags == OF_GPIO_ACTIVE_LOW ? GPIOF_ACTIVE_LOW : 0; 114 115 ret = devm_gpio_request_one(&spi->dev, gpio, flags, 116 "eeprom_93xx56_select"); 117 if (ret) 118 return ret; 119 120 pd->select = gpio_to_desc(gpio); 121 pd->prepare = select_assert; 122 pd->finish = select_deassert; 123 124 gpiod_direction_output(pd->select, 0); 125 } 126 127 spi->dev.platform_data = pd; 128 129 return 0; 130} 131 132static int eeprom_93xx56_probe(struct spi_device *spi ) 133{ 134 struct eeprom_93xx56_platform_data *pd; 135 struct eeprom_93xx56_dev *edev; 136 int err; 137 138 dev_err(&spi->dev,"spi:93xx56 probing....\n"); 139 if (spi->dev.of_node) { 140 err = eeprom_93xx56_probe_dt(spi); 141 if (err < 0) 142 return err; 143 } 144 145 pd = spi->dev.platform_data; 146 if (!pd) { 147 dev_err(&spi->dev, "missing platform data\n"); 148 return -ENODEV; 149 } 150 151 dev_err(&spi->dev,"spi:93xx56 memory setting..\n"); 152 edev = kzalloc(sizeof(*edev), GFP_KERNEL); 153 if (!edev) 154 return -ENOMEM; 155 156 if (pd->flags & EE_ADDR8) 157 edev->addrlen = ADDR_LEN_x8; 158 else if (pd->flags & EE_ADDR16) 159 edev->addrlen = ADDR_LEN_x8 - 1; 160 else { 161 dev_err(&spi->dev, "unspecified address type\n"); 162 err = -EINVAL; 163 goto fail; 164 } 165 166 mutex_init(&edev->lock); 167 168 edev->spi = spi; 169 edev->pdata = pd; 170 171 edev->size = 256; 172 173 dev_err(&spi->dev, "%d-bit eeprom %s\n", 174 (pd->flags & EE_ADDR8) ? 8 : 16, 175 (pd->flags & EE_READONLY) ? "(readonly)" : ""); 176 177 if (!(pd->flags & EE_READONLY)) { 178 if (device_create_file(&spi->dev, &dev_attr_erase)) 179 dev_err(&spi->dev, "can't create erase interface\n"); 180 } 181 182 spi_set_drvdata(spi, edev); 183 return 0; 184fail: 185 kfree(edev); 186 return err; 187} 188 189static int eeprom_93xx56_remove(struct spi_device *spi) 190{ 191 struct eeprom_93xx56_dev *edev = spi_get_drvdata(spi); 192 193 if (!(edev->pdata->flags & EE_READONLY)) 194 device_remove_file(&spi->dev, &dev_attr_erase); 195 196 kfree(edev); 197 return 0; 198} 199/* --------------------------- Driver Function Define -------------------------------- */ 200static const struct file_operations eeprom_93xx56_fops = { 201 .owner = THIS_MODULE, 202 /* REVISIT switch to aio primitives, so that userspace 203 * gets more complete API coverage. It'll simplify things 204 * too, except for the locking. 205 */ 206 .write = eeprom_93xx56_if_write, 207 .read = eeprom_93xx56_if_read, 208// .unlocked_ioctl = spieep_ioctl, 209// .compat_ioctl = spieep_compat_ioctl, 210 .open = eeprom_93xx56_if_open, 211 .release = eeprom_93xx56_if_release, 212// .llseek = no_llseek, 213}; 214 215static struct spi_driver eeprom_93xx56_driver = { 216 .driver = { 217 .name = "93xx56", 218 .owner = THIS_MODULE, 219 .of_match_table = of_match_ptr(eeprom_93xx56_of_table), 220 }, 221 .probe = eeprom_93xx56_probe, 222 .remove = eeprom_93xx56_remove, 223}; 224 225/* ------------------------------------------------------------------------------------ */ 226static int __init eeprom_93xx56_init(void) 227{ 228 int status; 229 230 /* Claim our 256 reserved device numbers. Then register a class 231 * that will key udev/mdev to add/remove /dev nodes. Last, register 232 * the driver which manages those device numbers. 233 */ 234 printk(KERN_ALERT "eep93xx56:init...\n"); 235 BUILD_BUG_ON(N_SPI_MINORS > 256); 236 status = register_chrdev(SPIDEV_MAJOR, "spi", &eeprom_93xx56_fops); 237 if (status < 0) 238 return status; 239 240 eeprom_93xx56_class = class_create(THIS_MODULE, "93xx56"); 241 if (IS_ERR(eeprom_93xx56_class)) { 242 printk(KERN_ALERT "class_create:93xx56 missed!!\n"); 243 unregister_chrdev(SPIDEV_MAJOR, eeprom_93xx56_driver.driver.name); 244 return PTR_ERR(eeprom_93xx56_class); 245 } 246 247 status = spi_register_driver(&eeprom_93xx56_driver); 248 if (status < 0) { 249 class_destroy(eeprom_93xx56_class); 250 unregister_chrdev(SPIDEV_MAJOR, eeprom_93xx56_driver.driver.name); 251 } 252 return status; 253} 254module_init(eeprom_93xx56_init); 255 256static void __exit eeprom_93xx56_exit(void) 257{ 258 spi_unregister_driver(&eeprom_93xx56_driver); 259 class_destroy(eeprom_93xx56_class); 260 unregister_chrdev(SPIDEV_MAJOR, eeprom_93xx56_driver.driver.name); 261} 262module_exit(eeprom_93xx56_exit); 263/* ----------------------------------------------------------------------------------- */ 264 265MODULE_LICENSE("GPL"); 266MODULE_DESCRIPTION("Driver for 93xx56 EEPROMs"); 267MODULE_AUTHOR("xxxx <xxxx@aaaa.bbb.cc>"); 268MODULE_ALIAS("spi:93xx56");

#わからないこと
デバイスツリーのcompatibleは同一になっています。
compatibleの中身だけを変更し、それに合った別の(元々あった)ドライバと関連付けると認識されるので、デバイスツリーは間違っていないと思っています。

このとき、init関数やprobe関数が呼ばれもしないのが何故なのかがわかりません。
カーネルがinit関数、probe関数を呼ばない要因など、ヒントになりそうなことがありましたらご教示いただけたらと思います。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sukekeke0

2020/12/10 14:12 編集

よろしければ状況の明確化のため教えてください。 > ちなみにmodprobeを使うと、正しく認識されているようです(lsmodで見ただけですが)。 modprobeコマンドを実行すると、意図した(自作の)ドライバをロードできており、 かつprintkの表示もdmesgで確認できた、ということでしょうか? > compatibleの中身だけを変更し、それに合った別の(元々あった)ドライバと関連付けると認識されるので、デバイスツリーは間違っていないと思っています。 デバイスツリーのcompatibleを既存のドライバと関連づけると、OS起動時にドライバが自動でロードされ、dmesgでprintkの表示を確認できた。しかし、compatibleを自作のドライバに関連づけた場合は、OS起動時に自動でロードされない(lsmodでドライバが表示されず、printkが走った形跡が無いのでinit,probeが呼ばれていない)。ということでしょうか?
hero1000

2020/12/10 23:48

>> ちなみにmodprobeを使うと、正しく認識されているようです(lsmodで見ただけですが)。 >modprobeコマンドを実行すると、意図した(自作の)ドライバをロードできており、 >かつprintkの表示もdmesgで確認できた、ということでしょうか? はい、そうです。 >デバイスツリーのcompatibleを既存のドライバと関連づけると、OS起動時にドライバが自動でロードさ>れ、dmesgでprintkの表示を確認できた。しかし、compatibleを自作のドライバに関連づけた場合は、>OS起動時に自動でロードされない(lsmodでドライバが表示されず、printkが走った形跡が無いので>init,probeが呼ばれていない)。ということでしょうか? はい、その通りです。
guest

回答1

0

自己解決

自己解決しました。

まずspi.cとspidev.cはどうやら必須らしく、デバイスツリーではspiにspi.c、その下に子としてspidev.cをぶら下げる必要があるようです。
私の自作ドライバはspidev.cのさらに子のノードにぶら下げることで認識されるようになりました。

ただ、spidev.cと私のドライバの動作は似たようなもの(もともと入れ替えるつもりだった)なので、メカニズムとしてははっきりしない感じ(一番嫌なやつですね)です。

投稿2020/12/11 06:07

hero1000

総合スコア56

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問