drm/amdgpu: Add MFD support for ISP I2C bus
authorVenkata Narendra Kumar Gutta <vengutta@amd.com>
Wed, 19 Jun 2024 01:16:52 +0000 (18:16 -0700)
committerAlex Deucher <alexander.deucher@amd.com>
Sat, 27 Jul 2024 21:28:58 +0000 (17:28 -0400)
ISP I2C bus device can't be enumerated via ACPI mechanism
since it shares the memory map with the AMDGPU.
So use the MFD mechanism for registering the ISP I2C device
and add the required resources.

Signed-off-by: Venkata Narendra Kumar Gutta <vengutta@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_isp.h
drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.c
drivers/gpu/drm/amd/amdgpu/isp_v4_1_0.h
drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c
drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.h

index 44e2ea8..b03664c 100644 (file)
@@ -49,6 +49,7 @@ struct amdgpu_isp {
        const struct isp_funcs  *funcs;
        struct mfd_cell *isp_cell;
        struct resource *isp_res;
+       struct resource *isp_i2c_res;
        struct isp_platform_data *isp_pdata;
        unsigned int harvest_config;
        const struct firmware   *fw;
index aac1078..964c29e 100644 (file)
@@ -42,23 +42,23 @@ static const unsigned int isp_4_1_0_int_srcid[MAX_ISP410_INT_SRC] = {
 static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
 {
        struct amdgpu_device *adev = isp->adev;
+       int idx, int_idx, num_res, r;
        u64 isp_base;
-       int int_idx;
-       int r;
 
        if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
                return -EINVAL;
 
        isp_base = adev->rmmio_base;
 
-       isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
+       isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL);
        if (!isp->isp_cell) {
                r = -ENOMEM;
                DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
                goto failure;
        }
 
-       isp->isp_res = kcalloc(MAX_ISP410_INT_SRC + 1, sizeof(struct resource),
+       num_res = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES + MAX_ISP410_INT_SRC;
+       isp->isp_res = kcalloc(num_res, sizeof(struct resource),
                               GFP_KERNEL);
        if (!isp->isp_res) {
                r = -ENOMEM;
@@ -83,22 +83,53 @@ static int isp_v4_1_0_hw_init(struct amdgpu_isp *isp)
        isp->isp_res[0].start = isp_base;
        isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;
 
-       for (int_idx = 0; int_idx < MAX_ISP410_INT_SRC; int_idx++) {
-               isp->isp_res[int_idx + 1].name = "isp_4_1_0_irq";
-               isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
-               isp->isp_res[int_idx + 1].start =
+       isp->isp_res[1].name = "isp_4_1_phy0_reg";
+       isp->isp_res[1].flags = IORESOURCE_MEM;
+       isp->isp_res[1].start = isp_base + ISP410_PHY0_OFFSET;
+       isp->isp_res[1].end = isp_base + ISP410_PHY0_OFFSET + ISP410_PHY0_SIZE;
+
+       isp->isp_res[2].name = "isp_gpio_sensor0_reg";
+       isp->isp_res[2].flags = IORESOURCE_MEM;
+       isp->isp_res[2].start = isp_base + ISP410_GPIO_SENSOR0_OFFSET;
+       isp->isp_res[2].end = isp_base + ISP410_GPIO_SENSOR0_OFFSET +
+                             ISP410_GPIO_SENSOR0_SIZE;
+
+       for (idx = MAX_ISP410_MEM_RES + MAX_ISP410_SENSOR_RES, int_idx = 0;
+            idx < num_res; idx++, int_idx++) {
+               isp->isp_res[idx].name = "isp_4_1_0_irq";
+               isp->isp_res[idx].flags = IORESOURCE_IRQ;
+               isp->isp_res[idx].start =
                        amdgpu_irq_create_mapping(adev, isp_4_1_0_int_srcid[int_idx]);
-               isp->isp_res[int_idx + 1].end =
-                       isp->isp_res[int_idx + 1].start;
+               isp->isp_res[idx].end =
+                       isp->isp_res[idx].start;
        }
 
        isp->isp_cell[0].name = "amd_isp_capture";
-       isp->isp_cell[0].num_resources = MAX_ISP410_INT_SRC + 1;
+       isp->isp_cell[0].num_resources = num_res;
        isp->isp_cell[0].resources = &isp->isp_res[0];
        isp->isp_cell[0].platform_data = isp->isp_pdata;
        isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
 
-       r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
+       isp->isp_i2c_res = kcalloc(1, sizeof(struct resource),
+                                  GFP_KERNEL);
+       if (!isp->isp_i2c_res) {
+               r = -ENOMEM;
+               DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
+               goto failure;
+       }
+
+       isp->isp_i2c_res[0].name = "isp_i2c0_reg";
+       isp->isp_i2c_res[0].flags = IORESOURCE_MEM;
+       isp->isp_i2c_res[0].start = isp_base + ISP410_I2C0_OFFSET;
+       isp->isp_i2c_res[0].end = isp_base + ISP410_I2C0_OFFSET + ISP410_I2C0_SIZE;
+
+       isp->isp_cell[1].name = "amd_isp_i2c_designware";
+       isp->isp_cell[1].num_resources = 1;
+       isp->isp_cell[1].resources = &isp->isp_i2c_res[0];
+       isp->isp_cell[1].platform_data = isp->isp_pdata;
+       isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data);
+
+       r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2);
        if (r) {
                DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
                goto failure;
@@ -111,6 +142,7 @@ failure:
        kfree(isp->isp_pdata);
        kfree(isp->isp_res);
        kfree(isp->isp_cell);
+       kfree(isp->isp_i2c_res);
 
        return r;
 }
@@ -122,6 +154,7 @@ static int isp_v4_1_0_hw_fini(struct amdgpu_isp *isp)
        kfree(isp->isp_res);
        kfree(isp->isp_cell);
        kfree(isp->isp_pdata);
+       kfree(isp->isp_i2c_res);
 
        return 0;
 }
index 315f282..7db24c0 100644 (file)
 
 #include "ivsrcid/isp/irqsrcs_isp_4_1.h"
 
+#define MAX_ISP410_MEM_RES 2
+#define MAX_ISP410_SENSOR_RES 1
 #define MAX_ISP410_INT_SRC 8
 
+#define ISP410_PHY0_OFFSET 0x66700
+#define ISP410_PHY0_SIZE   0xD30
+
+#define ISP410_I2C0_OFFSET 0x66400
+#define ISP410_I2C0_SIZE 0x100
+
+#define ISP410_GPIO_SENSOR0_OFFSET 0x6613C
+#define ISP410_GPIO_SENSOR0_SIZE 0x4
+
 void isp_v4_1_0_set_isp_funcs(struct amdgpu_isp *isp);
 
 #endif
index 4e17fa0..b56f272 100644 (file)
@@ -42,23 +42,24 @@ static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = {
 static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
 {
        struct amdgpu_device *adev = isp->adev;
+       int idx, int_idx, num_res, r;
        u64 isp_base;
-       int int_idx;
-       int r;
 
        if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
                return -EINVAL;
 
        isp_base = adev->rmmio_base;
 
-       isp->isp_cell = kcalloc(1, sizeof(struct mfd_cell), GFP_KERNEL);
+       isp->isp_cell = kcalloc(2, sizeof(struct mfd_cell), GFP_KERNEL);
        if (!isp->isp_cell) {
                r = -ENOMEM;
                DRM_ERROR("%s: isp mfd cell alloc failed\n", __func__);
                goto failure;
        }
 
-       isp->isp_res = kcalloc(MAX_ISP411_INT_SRC + 1, sizeof(struct resource),
+       num_res = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES + MAX_ISP411_INT_SRC;
+
+       isp->isp_res = kcalloc(num_res, sizeof(struct resource),
                               GFP_KERNEL);
        if (!isp->isp_res) {
                r = -ENOMEM;
@@ -83,22 +84,52 @@ static int isp_v4_1_1_hw_init(struct amdgpu_isp *isp)
        isp->isp_res[0].start = isp_base;
        isp->isp_res[0].end = isp_base + ISP_REGS_OFFSET_END;
 
-       for (int_idx = 0; int_idx < MAX_ISP411_INT_SRC; int_idx++) {
-               isp->isp_res[int_idx + 1].name = "isp_4_1_1_irq";
-               isp->isp_res[int_idx + 1].flags = IORESOURCE_IRQ;
-               isp->isp_res[int_idx + 1].start =
+       isp->isp_res[1].name = "isp_4_1_1_phy0_reg";
+       isp->isp_res[1].flags = IORESOURCE_MEM;
+       isp->isp_res[1].start = isp_base + ISP411_PHY0_OFFSET;
+       isp->isp_res[1].end = isp_base + ISP411_PHY0_OFFSET + ISP411_PHY0_SIZE;
+
+       isp->isp_res[2].name = "isp_4_1_1_sensor0_reg";
+       isp->isp_res[2].flags = IORESOURCE_MEM;
+       isp->isp_res[2].start = isp_base + ISP411_GPIO_SENSOR0_OFFSET;
+       isp->isp_res[2].end = isp_base + ISP411_GPIO_SENSOR0_OFFSET +
+                             ISP411_GPIO_SENSOR0_SIZE;
+
+       for (idx = MAX_ISP411_MEM_RES + MAX_ISP411_SENSOR_RES, int_idx = 0;
+            idx < num_res; idx++, int_idx++) {
+               isp->isp_res[idx].name = "isp_4_1_1_irq";
+               isp->isp_res[idx].flags = IORESOURCE_IRQ;
+               isp->isp_res[idx].start =
                        amdgpu_irq_create_mapping(adev, isp_4_1_1_int_srcid[int_idx]);
-               isp->isp_res[int_idx + 1].end =
-                       isp->isp_res[int_idx + 1].start;
+               isp->isp_res[idx].end =
+                       isp->isp_res[idx].start;
        }
 
        isp->isp_cell[0].name = "amd_isp_capture";
-       isp->isp_cell[0].num_resources = MAX_ISP411_INT_SRC + 1;
+       isp->isp_cell[0].num_resources = num_res;
        isp->isp_cell[0].resources = &isp->isp_res[0];
        isp->isp_cell[0].platform_data = isp->isp_pdata;
        isp->isp_cell[0].pdata_size = sizeof(struct isp_platform_data);
 
-       r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 1);
+       isp->isp_i2c_res = kcalloc(1, sizeof(struct resource), GFP_KERNEL);
+       if (!isp->isp_i2c_res) {
+               r = -ENOMEM;
+               DRM_ERROR("%s: isp mfd res alloc failed\n", __func__);
+               goto failure;
+       }
+
+       isp->isp_i2c_res[0].name = "isp_i2c0_reg";
+       isp->isp_i2c_res[0].flags = IORESOURCE_MEM;
+       isp->isp_i2c_res[0].start = isp_base + ISP411_I2C0_OFFSET;
+       isp->isp_i2c_res[0].end = isp_base + ISP411_I2C0_OFFSET + ISP411_I2C0_SIZE;
+
+       isp->isp_cell[1].name = "amd_isp_i2c_designware";
+       isp->isp_cell[1].num_resources = 1;
+       isp->isp_cell[1].resources = &isp->isp_i2c_res[0];
+       isp->isp_cell[1].platform_data = isp->isp_pdata;
+       isp->isp_cell[1].pdata_size = sizeof(struct isp_platform_data);
+
+       r = mfd_add_hotplug_devices(isp->parent, isp->isp_cell, 2);
        if (r) {
                DRM_ERROR("%s: add mfd hotplug device failed\n", __func__);
                goto failure;
@@ -111,6 +142,7 @@ failure:
        kfree(isp->isp_pdata);
        kfree(isp->isp_res);
        kfree(isp->isp_cell);
+       kfree(isp->isp_i2c_res);
 
        return r;
 }
@@ -122,6 +154,7 @@ static int isp_v4_1_1_hw_fini(struct amdgpu_isp *isp)
        kfree(isp->isp_res);
        kfree(isp->isp_cell);
        kfree(isp->isp_pdata);
+       kfree(isp->isp_i2c_res);
 
        return 0;
 }
index dfb9522..40887dd 100644 (file)
 
 #include "ivsrcid/isp/irqsrcs_isp_4_1.h"
 
+#define MAX_ISP411_MEM_RES 2
+#define MAX_ISP411_SENSOR_RES 1
 #define MAX_ISP411_INT_SRC 8
 
+#define ISP411_PHY0_OFFSET 0x66700
+#define ISP411_PHY0_SIZE   0xD30
+
+#define ISP411_I2C0_OFFSET 0x66400
+#define ISP411_I2C0_SIZE 0x100
+
+#define ISP411_GPIO_SENSOR0_OFFSET 0x6613C
+#define ISP411_GPIO_SENSOR0_SIZE 0x4
+
 void isp_v4_1_1_set_isp_funcs(struct amdgpu_isp *isp);
 
 #endif