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 44e2ea8c972826d03394e0b0b56aa0573dd5c578..b03664c66dd61789a501490e80a67d8cdb0e666b 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 aac107898baeccb2541b7b00ac5b588e5d949c10..964c29ef25dccdf16310555324037fe7a2745d1b 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 315f2822410c0e224c9f8dd2f3d744c570058fa7..7db24c0f1080807007a5aa023e38074490082ff6 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 4e17fa03f7b5f23b5ae134ddd486a4a88eacd5fc..b56f27295468f2a0c709b9ceb3379e208b14fe2c 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 dfb9522c9d6a2a2b1b08a3ec37c0772528aa7125..40887ddeb08c01afbe17e7a78b742f358ed5bcd5 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