-
[리눅스 커널] pinctrl - overviewLinux/kernel 2023. 12. 4. 01:11
글의 참고
- http://www.wowotech.net/gpio_subsystem/io-port-control.html
글의 전제
- 밑줄로 작성된 글은 강조 표시를 의미한다.
- 그림 출처는 항시 그림 아래에 표시했다.
글의 내용
- Overview
" embedded system engineer 로서 처음 일을 시작했을 때, 맡는 작업들은 대개 GPIO, button, LED 컨트롤 같은 작업들이다. 이러한 작업들의 공통점은 `쉬워보인다` 는 점이다. 물론, 앞에 언급된 디바이스들에 대한 드라이버가 이미 작성되어 있다면 `쉽다` 라는 표현이 맞을것이다. 그러나, 디바이스 드라이버를 작성해야 한다면 그게 어떤 OS 라 할지라도 혹은 bare metal 및 firmware 라면 얘기가 달라진다. 리눅스 같은 경우는 `어떻게 작성해야 하지?` 보다는 `어떻게 분석해야 하지?` 가 먼저가 된다. 왜냐면, kernel driver framework 에서 이미 pin controller subsystem 과 GPIO subsystem 이 이미 존재한다. 이걸 사용해서 드라이버를 개발해야 하는데, 어떤 API 를 사용해야 할지, 디바이스 트리에 무엇을 작성해야 하는지에 대해서 공부하다보면, 신입 개발자가 다루기에는 상당히 난이도가 높다는 것을 체감하게 된다. 그래서 나는 총 3 ~ 5 편 분량의 리눅스 커널의 pin controller subsystem & GPIO subsystem 관련 글을 작성할까 계획중이다. 물론, 나 자신을 위해서 작성하는 글이기 때문에 신입 개발자들을 위한 글이라고 말하지는 않겠다. 최소 1년 리눅스 디바이스 드라이버 업무를 경험해본 개발자들을 기준으로 글을 작성했다.
- Different GPIO control
" embedded software engineer`s 들은 항상 다양한 target board`s 들을 다루게 된다. 그리고, 각 보드의 GPIO`s 들을 컨트롤하는 방법은 다양하다.
1. GPIO`s 들이 CPU 와 연결된 방식이 다른 경우
" ARM`s embedded hardware platform 에서는 SoC 자체적으로 다수의 I/O ports 들을 제공한다. SoC 내부에서 존재하는 GPIO controller 는 SoC bus(AMBA) 를 통해서 CPU 와 연결된다. 그러나, 일부 peripheral chips 에서는 별도의 I/O ports 를 제공한다.
1. 일부 key controller chips, codecs, PMU chips 들은 별도의 I/O ports 들을 제공한다.
2. I/O ports 를 확장하기 위해서 사용하는 IO expander chip 같은 경우는 추가적으로 16 혹은 32 개의 GPIOs 를 제공한다." hardware 관점에서 보면, 즉, 회로도를 살펴보면 알게 되겠지만, peripheral 들이 제공하는 I/O ports 들과 SoC 에서 제공하는 I/O ports 구조적으로 완전히 다르다. 예를 들어, IO expander 는 일반적으로 CPU 와 I2C 를 통해 연결된다. 즉, CPU 는 I2C 를 통해 추가적인 GPIO`s(IO expander) 들을 컨트롤하게 되는 것이다. 그러나, SoC 내부에 존재하는 I/O ports 는 관련 register 에 특정 값을 write 함으로써 GPIO`s 들을 컨트롤할 수 있다.
" 2개의 차이를 절대 간과해서는 안된다. SoC memory map register 에 특정 값을 write 하는 것은 속도면에서 굉장히 빠르다. 그런, I2C 를 통해서 I/O operation 을 진행하는 것은 register access 보다 속도가 현저히 느리다. 그리고, bus 가 busy 한 상황이라면, 현재 작업중인 process 를 어쩌면 blocked 해야 될 수도 있다. 이러한, 경우에 반드시 kernel synchronization mechanism 을 고려해야 한다. 예를 들어, GPIO 가 sleep 을 유발한다면(예를 들어, I2C 버스가 사용중이라면), spinlock 은 사용할 수 없다.
2. GPIO control 방식이 다른 경우
" 대다수의 SoC GPIO controller 에서는 1개의 레지스터만 가지고도 물리적인 output signal level 를 변경할 수 있다. 예를 들어, GPIO_DATA_REG 에 0을 쓰면, output signal level 가 0 이 되고, 1을 쓰면 output signal level 이 1 이 된다. 그러나, 일부 SoC GPIO controller 에서는 2개의 레지스터를 통해서 물리적인 output signal level 를 변경해야 한다. 예를 들어, GPIO_DATA_HIGH_REG / GPIO_DATA_LOW_REG 레지스터가 존재한다고 치자. GPIO_DATA_HIGH_REG 에 1 을 쓰면 output signal level 이 1 이 된다. 그리고, GPIO_DATA_LOW_REG 에 1 을 쓰면, output signal level 가 0 이 된다.
3. GPIO feature 가 다른 경우
" 굉장히 다양한 케이스들이 있지만, 여기서는 3 가지 정도만 추려서 살펴본다.
1. interrupt pin 으로 설정이 가능한지 여부. 모든 I/O ports 가 interrupt 기능을 지원하는 것은 아니다. 일부 CPU 들은 1개 혹은 2개 정도의 GPIO`s 그룹(IO ports)에서만 interrupt 기능을 지원된다.
2. 만약, GPIO 를 interrupt pin 으로 설정 가능하다면, 해당 GPIO 가 sleep 상태에 있는 system 을 wake-up 시킬 수 있는지 여부.
3. 일부 GPIO`s 들은 software 적으로 컨트롤이 가능한 pull-up / pull-down register 이 연결되어 있다. 심지어, 100k, 30k, 1k 등 다양한 pull-up 설정이 가능하다. 거기다가, 일부 GPIO`s 들은 input 으로 설정될 경우, debounce 까지 지원하는 경우도 많다.4. GPIO function 이 다양할 경우
" 일부 GPIO`s 들은 단순히 GPIO 만을 나타낸다. 또 다른 일부는 다양한 functions 들을 가지고 있는 경우도 있다. 예를 들어, IO expander 의 GPIO`s 들은 정말 단순히 GPIO 기능만을 나타낸다. 그러나, SoC 내부에 존재하는 GPIO`s 들은 alfternative function 이라해서 GPIO, CS, SDA, MDM_CLK, SPI_MISO 등 다양한 기능으로 multiplex 될 수 있다.
- Pin functin classification in hardware
" SoC Pin(I2C, SPI, UART, ADC, GPIO, etc) 등을 컨트롤하기 위해서 device datasheet 를 살펴보면, 항상 GPIO controller 혹은 I/O port 라는 chapter 가 존재한다. 그런데, 문제는 pin 관련 레지스터가 너무 많다는 것이다. 그러나, 다행히도 필요한 부분은 대개 정해져있다. 크게 3 가지로 나눠 볼 수 있다.
1. 우리가 흔히 pin control 이라는 부르는 기능은 2가지로 나뉜다.
1. Pin function configuration - I/O pin 을 어떤 목적으로 사용할지를 설정한다. 예를 들어, GPIO 로 사용할 것인지, special function(CS, CLK, SDA etc) 으로 설정할지를 설정한다.
2. Pin feature configuration - Pull-up/down 저항, drive-strengh 설정.2. 만약, 특정 GPIO`s 들이 SPI 로 설정되면, 해당 핀들은 SPI controller 에 연결된다. 만약, 특정 GPIO`s 들이 GPIO 로 설정되면, GPIO controller 에 연결된다. GPIO controller 레지스터에 access 함으로써 software 는 아래의 기능들을 수행할 수 있다.
1. GPIO direction 설정한다.
2. 만약, direction 이 output 라면, output signal 이 high 인지 low 인지를 설정한다.
3. 만약, direction 이 input 라면, active-high 인지 active-low 인지를 설정한다.3. 만약, 특정 GPIO`s 들을 interrupt 로 설정할 수 있다면, 비록 datasheet 에는 interrupt 설정 내용이 GPIO chapter 에 있더라도, 하드웨어적으로 이 GPIO`s 들은 GPIO controller 보다는 interrupt controller 쪽에 속해있다. 즉, GPIO 타입의 인터럽트라고 보는 것이 더 맞는 표현이라 할 수 있다. 이러한 GPIO`s 타입의 인터럽트 레지스터를 통해서 아래와 같은 기능들을 컨트롤할 수 있다.
1. interrupt enable and disable (mask and unmask)
2. trigger mode (edge-trigger or level-trigger)
3. interrupt status cleared- How to abstract the different function of hardware
" 예전 linux kenrel 의 GPIO controller subsystem 는 GPIO direction, GPIO output signal, GPIO input level 정도만 컨트롤할 수 있었다. 반면에, 현대의 linux kenel GPIO controller subsystem 는 위 섹션에서 설명한 3 가지 기능을 모두 소프트웨어적으로 지원한다.
1. pin control subsystem - pin controller hardware 를 컨트롤하는 software subsystem.
2. GPIO subsystem - GPIO controller hardware 를 컨트롤하는 software subsystem.
3. GPIO interrupt chip driver - GPIO interrupt controller hardware 를 컨트롤하는 software subsystem. 그러나, 이 software subsystem 은 interrupt subsystem 을 의미한다. 그러므로, 이 내용은 이 글에서 다루지 않는다. 별도의 인터럽트 관련 글에서 다루도록 한다.1. pin control subsystem block diagram
" 아래 다이어그램은 리눅스 커널의 pin control subsystem 을 나타낸다.
" 일반적인 드라이버에서 pin controller hardware 가 제공하는 기능을 사용하기 위해서는 driver-specific pin controller driver 가 커널에 등록되야 한다. pin controller driver 제조사는 먼저 pin controller hardware 를 소프트웨어로 추상화시킬 수 있는 자료 구조(구조체)를 직접 만들어야 한다. 그리고, 해당 구조체를 생성해서 데이터를 채워넣은 뒤, pin control subsystem(kernel) 에서 제공하는 API(pinctrl_register() 함수)를 호출해서 커널에 등록해야 한다. kernel driver framework 들이 대부분(regulator, clock, interrupt, etc) 그렇지만, core module 은 hardware 와 independent 하게 존재한다. 즉, kernel driver core module 은 hardware 를 추상화시켜 consumer driver layer 에 일관된 인터페이스를 제공한다.
2. GPIO subsystem block diagram
" 아래 다이어그램은 리눅스 커널의 GPIO subsystem 을 나타낸다.
" GPIO subsystem 은 Pin controller subsystem 과 상당히 유사하다. 물론, 내부 로직은 상당히 다르다. 해당 내용은 이어지는 글에서 설명한다.
'Linux > kernel' 카테고리의 다른 글
[리눅스 커널] Interrupt - GICv2 part 2 (0) 2023.12.24 [리눅스 커널] DMA - cache consistency (0) 2023.12.06 [리눅스 커널] DMA - overview (0) 2023.12.01 [리눅스 커널] DD - character device (0) 2023.11.29 [리눅스 커널] Scheduler - process address space switching (0) 2023.11.21