Blog / gx chip driver / gx chip driver

Gx Chip Driver Apr 2026

struct gx_mem_region phys_addr_t start; size_t size; void *cookie; struct list_head list; ; // Allocation from reserved CMA pool void *gx_mem_alloc(size_t size, u32 align); void gx_mem_free(void *handle);

echo 0x1f > /sys/module/gx_vpu/parameters/debug to enable verbose logging. Check cat /proc/interrupts | grep vpu for interrupt count. 4.4 I2C / SPI Drivers ( gx_i2c , gx_spi ) These are simple wrapper drivers around DesignWare IP or a custom bit-bang. The GX implementation often lacks proper clock gating or recovery on bus hang.

If you can avoid GX for a new design, do so. If you're stuck, copy working register dumps from a known-good Android build and compare to your driver’s init sequence. gx chip driver

VPU_REG_DEC_CTRL (0xF100_0000) VPU_REG_STATUS (0xF100_0004) // bit 0 = busy VPU_REG_DATA (0xF100_0008) // firmware mailbox Driver requests gx_vpu_fw.bin from /lib/firmware . Missing firmware → VPU fails to start.

gx_mem: allocation failed (size=4194304) → Increase CMA size in bootargs: cma=384M or adjust per-pool sizes in device tree. 7. Device Tree Bindings (Example for GX350) &gx_vpu compatible = "nationalchip,gx350-vpu"; reg = <0x0 0xf1000000 0x0 0x4000>; interrupts = <0 33 4>; clocks = <&clkc GX350_CLK_VPU>, <&clkc GX350_CLK_VPU_AXI>; clock-names = "core", "bus"; firmware-name = "gx_vpu_fw.bin"; memory-region = <&vpu_mem>; ; &gx_disp compatible = "nationalchip,gx350-disp"; reg = <0x0 0xf0000000 0x0 0x2000>; interrupts = <0 25 4>; ports disp_out: endpoint remote-endpoint = <&hdmi_in>; ; ; ; The GX implementation often lacks proper clock gating

#define I2C_CON 0x00 #define I2C_TAR 0x04 #define I2C_DATA_CMD 0x10 #define I2C_ENABLE 0x6C static inline void gx_i2c_writel(struct gx_i2c *i2c, u32 val, u32 reg)

Userspace (GStreamer V4L2) → ioctl(VIDIOC_QBUF) → driver copies bitstream to SRAM/CMA → triggers VPU via mailbox → VPU interrupts on frame done → driver queues decoded frame to capture buffer. reg = &lt

struct gx_disp *disp = dev_id; u32 status = readl(disp->base + DISP_IRQ_STS); if (status & DISP_IRQ_VSYNC) writel(DISP_IRQ_VSYNC, disp->base + DISP_IRQ_STS); drm_crtc_handle_vblank(&disp->crtc); return IRQ_HANDLED;

// In gx_i2c_xfer(), add recovery if (status & I2C_STAT_BUS_BUSY) gx_i2c_reset(adap); mdelay(1);

writel_relaxed(val, i2c->base + reg);