OpenWRTのAR5315版のLinux Kernelのシリアルの初期化

AR5315でシリアルの操作を行なう前に[AT互換機版のLinux Kernel 2.6のブートからシリアルの初期化まで](linux_boot.html) でAT互換機版のシリアルの初期化に関して調べた。ここでは、OpenWRTのAR5315版のLinux Kernel独自な部分に関して説明をする。

AR5315版でも、カーネルのstart_kernelが呼ばれる。AT互換機版と違いstart_kernelが呼ばれるまでに何段ものステップを経由しないが、複数のデバイスをサポートするためにマクロを多用したものになっている。AT互換機版と同様にstart_kernelはsetup_archを呼び、アーキテクチャ依存のセットアップをする。setup_archは、MIPS依存だが、AR5315には依存していない。setup_archはprom_initやarch_mem_initなどを呼びだしAR5315依存のセットアップを行なう。

ar5315_plat_setupは、serial_setupを呼ぶことでAR5315の8250互換デバイスに関する情報を8250のデバイスドライバに登録する。互換デバイスはAT互換機では、IOポートを経由するが、AR5315では、メモリを経由する。8250互換デバイスのアドレスはKSEG1ADDR(AR5315_UART0) (アドレス0xB1100003)で得られる。また、AT互換機の8250は18.432MHzで動作するが、AR5315の8250互換デバイスは、ar5315_apb_frequency()で得られるAPB (Advanced Peripheral Bus)のクロック(92MHz)で動作する。8250互換デバイスの動作周波数は、シリアルの速度を設定するために使われる。

今回は、9600bpsでシリアルで文字を出力することにした。8250の操作方法に関してはExtBeyond Logicが詳しい。8250は1ビット送信するのに16クロック必要なことから、8250互換デバイスを9600bpsに設定するには、

8250の動作クロック / (通信速度 * 16) = 92MHz / (9600 * 16)
                                = 598.9583333...

を四捨五入して、599を使う。この計算はdrivers/serial/serial_core.cのuart_get_divisorで行なわれる。

_start (arch/mips/kernel/head.S)
  kernel_entry (arch/mips/kernel/head.S)
    start_kernel (init/main.c)
      setup_arch (arch/mips/kernel/setup.c)
        prom_init (arch/mips/atheros/prom.c)
          ar5315_prom_init (arch/mips/atheros/ar5315/board.c)
              AR5315_MEM_CFG
              AR5315_SREV
        arch_mem_init (arch/mips/kernel/setup.c)
          plat_mem_setup (arch/mips/atheros/board.c)
             ar5315_plat_setup (arch/mips/atheros/ar5315/board.c)
                 AR5315_AHB_ERR0
                 AR5315_AHB_ERR1
                 AR5315_WDC
                 AR5315_UART0 (include/asm-mips/mach-atheros/ar5315/ar5315.h)
               ar5315_apb_frequency (arch/mips/atheros/board.c)
               serial_setup (arch/mips/atheros/board.c)
                   uart_port (include/linux/serial_core.h)
                   mapbase = AR5315_UART0
                   s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
                   s.iotype = UPIO_MEM;
                   s.irq = AR531X_MISC_IRQ_UART0;
                   s.regshift = 2;
                   s.mapbase = mapbase;
                   s.uartclk = uartclk;
                   s.membase = (void __iomem *)s.mapbase;
                 early_serial_setup (drivers/serial/8250.c)
                   serial8250_isa_init_ports (drivers/serial/8250.c)
      console_init (called from start_kernel)
      rest_init

紹介 kiidax
元、環境非依存な職業プログラマー。Blenderで遊んでいます。

One Response to OpenWRTのAR5315版のLinux Kernelのシリアルの初期化

  1. ピンバック: jtag « KIIDAX

コメントを残す