Driver for RTS5227/RTS5229

After reinstall OS, the SD card reader on my laptop stops work again. Because this time I use Linux Mint, which is based on higher version kernel, I encountered more troubles to drive the SD card reader.

Three steps, five errors and solutions are recorded.

Step 1) Detect Device

Usually, SD card reader is connected to either pci bus or usb bus, so look up in the outputs of the following two command:

lspci
lsusb

What I found is:

03:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd. RTS5229 PCI Express Card Reader (rev 01)

That tells me the model of the SD card reader on my laptop is RTS5229, produced by Realtek Semiconductor.

Step 2) Get Proper Driver

So I searched driver for RTS5229, and found two solutions:

Solution 1) linux-firmware-nonfree package

I learnt from this post that there is a package called linux-firmware-nonfree to drive RTS5229. While this package is not in Ubuntu 16.04 source list any longer. Although download the package then use dpkg to install it might work, it is risky to do so.

Solution 2) build from source

This is the solution which should be safer and finally works for me. But the source files I downloaded from Realtek website is for lower version of kernel. So several errors occurred when I executed sudo make.

Werror=date-time

rts5229/rtsx.c:148:55: error: macro "__DATE__" might prevent reproducible builds [-Werror=date-time]
  SPRINTF("        Build: %s, %s\n", __DATE__, __TIME__);

Compiler recognizes the warnings related to date-time as errors and prevents it from compile. Adding a flag -Wno-error=date-time to the EXTRA_CFLAGS variable in the Makefile can tell the compiler to ignore this error.

No rule to make target

make[2]: *** No rule to make target 'arch/x86/entry/syscalls/syscall_32.tbl', needed by 'arch/x86/entry/syscalls/../../include/generated/asm/syscalls_32.h'.  Stop

This is caused by kernel that $(PWD) does not work well in kernel header files folder. So change $(PWD) in the Makefile to $(shell pwd).

unknown field

rts5229/rtsx.c:266:2: error: unknown field ‘proc_info’ specified in initializer
  .proc_info =   proc_info,

This field is removed away from new versions of kernel, so comment this line.

deprecated __dev… macros

rts5229/rtsx.c:914:22: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtsx_probe’
 static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_idrts5229/rtsx.c:1069:23: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtsx_remove’
  static void __devexit rtsx_remove(struct pci_dev *pci)
rts5229/rtsx.c:1095:12: error: implicit declaration of function ‘__devexit_p’ [-Werror=implicit-function-declaration]
  .remove = __devexit_p(rtsx_remove)

I am using 4.10.0-38-generic, so I need to remove those macros according to the porting guide.

vmalloc header

rts5229/rtsx_chip.c:1131:16: error: implicit declaration of function ‘vmalloc’ [-Werror=implicit-function-declaration]
  data = (u32 *)vmalloc(dw_len * 4);

Add #include <linux/vmalloc.h> to the relevant files, including rtsx.c, rtsx_chip.c, rtsx_scsi.c and ms.c.

Above are all the errors I ran into.

Step 3) Install the Driver

To put the driver compiled in the second solution into use, do the following operations:

sudo make install
sudo modeprobe -r rtsx_pci
sudo depmod -a
sudo modprobe rts5229

Those commands remove the useless rtsx_pci and update module list then insert newly compiled driver.

If you are told rtsx_pci is in use and cannot be removed, unload its dependencies in order:

sudo modeprobe -r rtsx_pci_sdmmc
sudo modeprobe -r rtsx_pci_ms

To block OS from automatically selecting rtsx_pci as driver, add the following line in file /etc/modprobe.d/blacklist.conf:

blacklist rtsx_pci

Then execute:

sudo update-initramfs -u

To verify that newly compiled driver is used, execute command:

lspci -v

And you should see the RTS5229 device information has a line:

    Kernel driver in use: rts5229

If not, try restarting laptop to initialize device tree again.

Credits