라즈베리파이 4B device tree (SPI0) 질문드립니다.

sheld2의 이미지

안녕하세요.

파이4B로 device tree 를 공부중에 있습니다
파이에서 /boot/config.txt 에서 dtparam=spi=on 을 하면 관련 spi driver (spidev0.0, spidev0.1) 가 load 되는데요, 어떻게 해당 driver 들이 load 되는 건지 헷갈리네요.

일단 해당 driver 의 source code는 kernel tree 에서 /drivers/spi/spidev.c 라고 생각하고 있습니다.
code 내부를 보면 driver 의 이름이 spidev 라고 만들어지도록 되어있고요.

Device tree 관련해서 찾아보면, 'compatible' 에 써있는 값을 가지고 kernel 이 load 된 device tree 와 연관된 driver 를 찾는다고 알고있습니다만, spidev.c 가 가진 compatible 항목들은 아래와 같네요.

*********************************
#ifdef CONFIG_OF
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
{ .compatible = "ge,achc" },
{ .compatible = "semtech,sx1301" },
{ .compatible = "lwn,bk4" },
{ .compatible = "dh,dhcom-board" },
{ .compatible = "menlo,m53cpld" },
{},
};
*********************************

무언가 bcm2711 이라던지, 아니면 bcm2835 비스므리한 내용이 써있을꺼라고 생각했는데 그렇지않네요.
오히려 spi-bcm2835.c 가 가진 compatible 항목이 좀더 알맞은 것처럼 보입니다.

이 spidev0.0, spidev0.1 이 load 된 이유가, 위 compatible 과는 상관없이 기본 tree 인 "bcm2711-rpi-4-b.dts" 에서 기인하는 것인지 궁금하네요. 이 파일 내용을 들여다보면 아래와 같이 &spi0 항목에 spidev0 가 있기 때문에 그런것인가요?

*********************************
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
cs-gpios = <&gpio 8 1>, <&gpio 7 1>;

spidev0: spidev@0{
compatible = "spidev";
reg = <0>; /* CE0 */
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <125000000>;
};

spidev1: spidev@1{
compatible = "spidev";
reg = <1>; /* CE1 */
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <125000000>;
};
};
*********************************

고수분들의 도움 부탁드립니다..

bushi의 이미지

https://wikidocs.net/3205 에 따르면 로더(start.elf?)가 dtb 의 내용 중 /soc/spi@*/status 를 okay 로 바꾸는 것 같습니다.
starte.elf 는 오픈 소스가 아니니 매뉴얼에 써 있는 것 외엔 딱히 볼 만한게 없네요.
어떤 커널을 쓰시는지 모르겠지만, https://elixir.bootlin.com/linux/v5.8.13/source/arch/arm/boot/dts/bcm283x.dtsi#L327https://elixir.bootlin.com/linux/v5.8.13/source/arch/arm/boot/dts/bcm2711.dtsi#L154 처럼
spi0 에 대한 내용도 어딘가에 있거나 alias 로 만들어져 있어야 &spi0 { } 같은 식으로 override 가 가능합니다.

sheld2의 이미지

댓글 감사합니다.

Kernel 은 5.4.59-v7l+ 를 사용중이고 (라즈베리파이용),
몇가지 더 확인해보니 config.txt 에서 dtparam=spi-on 을 했을 때, bcm283x.dtsi 에 있는 spi 가 "okay" 로 enable 됩니다 (dtc -I fs /proc/device-tree 를 이용해 확인).

근데 그 spi 의 속성에도, "compatible = "brcm,bcm2835-spi"; 이라고 되어있습니다.

spidev.c 에 대해서는,
rmmod 로 spidev0.0, spidev0.1 을 내리고
/kernel/drivers/spidev.ko 를 insmod 로 올려보면 /dev 에 spidev0.0 과 spidev0.1 이 다시나타납니다.
즉, spidev0.0, 1을 만드는 놈은 spidev.c 가 확실한 것 같은데요.

spidev 는 linux standard driver 라는데, 이와 관련해서 무슨 내부적으로 다른 짓을 하는 것인지..ㅎㅎ

암튼 Pi 포럼쪽에도 글을 올려서 왜 그런지 이유를 확인을 해보려는 상태입니다.

감사합니다.

bushi의 이미지

뭘 모르고 계신지 모르니 중언부언하게 되네요.

parent node 에 status 프로퍼티가 있는데 그 값이 "okay" 나 "ok" 가 아니라면, 그 node 의 child node 들은 전부 무시됩니다.
spi0 노드의 status 프로퍼티가 "disabled" 라면, spi0 노드의 자식 노드들인 spidev 노드들에 대해선 platform/of_device 들이 만들어지지 않는다는 뜻입니다.
device 들이 만들어지지 않았으니 driver 가 있다해도 bind 될 턱이 없으므로, driver 가 /dev/spidev 등의 장치를 만들지 않습니다.
더 궁금한게 있으면 https://elixir.bootlin.com/linux/v5.4.59/source/drivers/of/ 공부하세요.

익명 사용자의 이미지

안녕하세요? 댓글 감사합니다.

초보자로써 잘아시는 분과 argue 하고싶은 생각은 없습니다만,
제가 무엇을 의문으로 여기는지 이해하지 못하시는 듯 합니다.

다시한번 정리하면,
device tree 나 spi driver source 에서 제가 임의로 변경한 것은 아무것도 없는 상태에서
config.txt 에서 dtparam=spi=on 으로 설정하고 부팅하면 /dev/spidev0.0, spidev0.1 이라는 device가 생깁니다.

여기서 dtparam=spi=on 을 했을 때와 이부분을 #처리하여 사용하지 않음으로 했을 때의 dtb 를 runtime으로 확인했을 때(dtc 커맨드 활용), 차이점은 spi node의 status="okay" 로 된다는 것입니다.
즉, spi=on을 하면 spi 노드가 활성화된다는거죠.

그런데 이 node가 가진 compatible="bcrm,bcm2835-spi" 입니다.
그래서 kernel/driver/spi/에서 compatible="bcrm,bcm2835-spi" 라는 것을 가진 driver source는 spi-bcrm2835.c 이고 이 driver 의 이름은 .name=DRV_NAME; // spi-bcm2835 입니다.

즉, 같은 compatible을 가진 driver를 찾아서 /dev/spi-bcm2835 가 생겨야할 것 같은데 왜 spidev0.0, spidev0.1 가 생기냐 이거죠. 이게 제가 이해가 안되는 부분입니다.

감사합니다.

bushi의 이미지

compatible="spidev" 를 가진 spidev 노드들은 compatible="bcm2835-spi" 를 가진 spi0 노드의 자식 노드이며,
spi0 노드가 okay 가 아닐 경우에 그 자식 노드들에 대해선 spidev0 등의 platform/of_device 가 생성되지도 않으며,
따라서 platform bus 에서 spidev.c 드라이버에 있는 .probe() 콜백을 호출할 턱이 없으므로 /dev/spidev0 따위의 장치노드가 만들어지지 않는다고 장문에 걸쳐 설명을 드렸습니다.

뭘 모르고 계시는지 정말 모르겠습니다. 같은 질문에 같은 답변이 계속 반복될 것 같은데, 아쉽네요.

AustinKim의 이미지

다음 패치를 적용한 후 커널 로그를 한 번 받아 보시겠어요?

diff --git a/drivers/of/base.c b/drivers/of/base.c
index db7fbc0..2fb26a7 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -637,6 +637,9 @@ static bool __of_device_is_available(const struct device_node *device)
                return true;
 
        if (statlen > 0) {
+               printk("[+][dts_debug] name: %s, full_name: %s, status: %s \n",
+                                                                       device->name, device->full_name, status);
+               dump_stack();
                if (!strcmp(status, "okay") || !strcmp(status, "ok"))
                        return true;
        }

커널 로그에서 디바이스 트리의 spi 관련 노드 정보를 확인할 수 있을 것이라 보입니다.

(개인블로그)
http://rousalome.egloos.com

sheld2의 이미지

안녕하세요 AustinKim 님.
예전에 댓글 달아주셨었는데 아래 댓글과 같이 궁금증이 해결되었네요.
며칠전에는 쓰신 책.. 리눅스 커널.. 라즈베리파이 책 2권을 구매했네요.ㅎㅎ
캐나다로 돌아갈 때 가지고 가려고합니다.ㅋ

AustinKim의 이미지

댓글이 도움이 됐다니 다행이네요.
제가 쓴 책을 읽어주셔서 감사드립니다. 혹시 궁금한 점이 있으면 아래 링크에서 질문을
남겨주시면 바로 피드백드리겠습니다.

http://rousalome.egloos.com/10020325

감사합니다.

(개인블로그)
http://rousalome.egloos.com

sheld2의 이미지

제가 올린 질문에 대해 제가 확인한 내용을 답변으로 답니다.
같은 궁금증을 가진 분들이 계신다면 도움이 될 듯 하네요.

제가 DT와 .compatible 에 대해서 웹과 참고도서에서 배운 바로는,
DT 에서 compatible 항목에 있는 이름과, 관련된 driver 안에있는 compatible 항목의 이름이 서로 일치해야 그 driver 가 정상적으로 loading 이 됩니다.
그러나 위 spidev.c 같은 경우는 compatible 이 다른데도 정상적으로 올라옵니다.

확인해보니, DT 에서의 compatible 의 이름이 driver 의 compatible 과 일치하지 않아도
그게 driver 의 name 과 일치하면 그 driver 가 정상적으로 올라옵니다.

즉, driver 가 올라올 수 있는 필요조건 중 하나는 다음과 같네요.
1) DT 에 있는 compatible 이름이 driver 의 compatible 중에 있다. 또는,
2) DT 에 있는 compatible 이름이 driver 의 name 과 같다.

이는 spidev 외에 다른 input device 용 driver 로 테스트해보았을 때도 마찬가지네요.

그럼이만..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.