On Mon, Mar 2, 2020 at 2:24 PM Andrey Grodzovsky <andrey.grodzovsky@xxxxxxx> wrote: > > Starts USBC PD FW download and reads back the latest FW version. > > Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@xxxxxxx> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 94 +++++++++++++++++++++++++++++++++ > 1 file changed, 94 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c > index d33f741..76630b9 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c > @@ -24,6 +24,7 @@ > */ > > #include <linux/firmware.h> > +#include <linux/dma-mapping.h> > > #include "amdgpu.h" > #include "amdgpu_psp.h" > @@ -38,6 +39,9 @@ > > static void psp_set_funcs(struct amdgpu_device *adev); > > +static int psp_sysfs_init(struct amdgpu_device *adev); > +static void psp_sysfs_fini(struct amdgpu_device *adev); > + > /* > * Due to DF Cstate management centralized to PMFW, the firmware > * loading sequence will be updated as below: > @@ -94,6 +98,7 @@ static int psp_early_init(void *handle) > psp->autoload_supported = false; > break; > case CHIP_NAVI10: > + psp_sysfs_init(adev); We should add the file as late as possible. Maybe add a new psp_late_init() function in amdgpu_psp.c? Otherwise, you'll get processes trying to use the sysfs interface before the driver is ready. Alex > case CHIP_NAVI14: > case CHIP_NAVI12: > psp_v11_0_set_psp_funcs(psp); > @@ -152,6 +157,10 @@ static int psp_sw_fini(void *handle) > release_firmware(adev->psp.ta_fw); > adev->psp.ta_fw = NULL; > } > + > + if (adev->asic_type == CHIP_NAVI10) > + psp_sysfs_fini(adev); > + > return 0; > } > > @@ -1816,6 +1825,76 @@ static int psp_set_powergating_state(void *handle, > return 0; > } > > +static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev, > + struct device_attribute *attr, > + char *buf) > +{ > + struct drm_device *ddev = dev_get_drvdata(dev); > + struct amdgpu_device *adev = ddev->dev_private; > + uint32_t fw_ver; > + int ret; > + > + ret = psp_read_usbc_pd_fw(&adev->psp, &fw_ver); > + if (ret) { > + DRM_ERROR("Failed to read USBC PD FW, err = %d", ret); > + return ret; > + } > + > + return snprintf(buf, PAGE_SIZE, "%x\n", fw_ver); > +} > + > +static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev, > + struct device_attribute *attr, > + const char *buf, > + size_t count) > +{ > + struct drm_device *ddev = dev_get_drvdata(dev); > + struct amdgpu_device *adev = ddev->dev_private; > + void *cpu_addr; > + dma_addr_t dma_addr; > + int ret = 0; > + char fw_name[100]; > + const struct firmware *usbc_pd_fw; > + > + > + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf); > + ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev); > + if (ret) > + goto fail; > + > + /* We need contiguous physical mem to place the FW for psp to access */ > + cpu_addr = dma_alloc_coherent(adev->dev, usbc_pd_fw->size, &dma_addr, GFP_KERNEL); > + > + ret = dma_mapping_error(adev->dev, dma_addr); > + if (ret) > + goto rel_buf; > + > + memcpy_toio(cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size); > + > + /*TODO Remove once PSP starts snooping CPU cache */ > + clflush_cache_range(cpu_addr, (usbc_pd_fw->size & ~(L1_CACHE_BYTES - 1))); > + > + ret = psp_load_usbc_pd_fw(&adev->psp, dma_addr); > + > +rel_buf: > + dma_free_coherent(adev->dev, usbc_pd_fw->size, cpu_addr, dma_addr); > + release_firmware(usbc_pd_fw); > + > +fail: > + if (ret) { > + DRM_ERROR("Failed to load USBC PD FW, err = %d", ret); > + return ret; > + } > + > + return count; > +} > + > +static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR, > + psp_usbc_pd_fw_sysfs_read, > + psp_usbc_pd_fw_sysfs_write); > + > + > + > const struct amd_ip_funcs psp_ip_funcs = { > .name = "psp", > .early_init = psp_early_init, > @@ -1834,6 +1913,21 @@ const struct amd_ip_funcs psp_ip_funcs = { > .set_powergating_state = psp_set_powergating_state, > }; > > +static int psp_sysfs_init(struct amdgpu_device *adev) > +{ > + int ret = device_create_file(adev->dev, &dev_attr_usbc_pd_fw); > + > + if (ret) > + DRM_ERROR("Failed to create USBC PD FW control file!"); > + > + return ret; > +} > + > +static void psp_sysfs_fini(struct amdgpu_device *adev) > +{ > + device_remove_file(adev->dev, &dev_attr_usbc_pd_fw); > +} > + > static const struct amdgpu_psp_funcs psp_funcs = { > .check_fw_loading_status = psp_check_fw_loading_status, > }; > -- > 2.7.4 > > _______________________________________________ > amd-gfx mailing list > amd-gfx@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/amd-gfx _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx